diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 0000000000..c6e603f450 --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,17 @@ +name: 'Dependency Review' +on: [pull_request] + +permissions: + contents: read + pull-requests: write + +jobs: + dependency-review: + runs-on: ubuntu-latest + steps: + - name: 'Checkout Repository' + uses: actions/checkout@v4 + - name: 'Dependency Review' + uses: actions/dependency-review-action@v4 + with: + comment-summary-in-pr: on-failure diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 7ab04208e6..4bc5b6ef05 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -58,11 +58,6 @@ jobs: # only informational so swallow error codes - run: npm outdated || exit 0 - # Audit - - run: npm audit --only=prod - # https://github.com/ni/nimble/issues/801 - # - run: npm audit --audit-level=critical - # Build - run: npm run build diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index b6570fceeb..8003ae7ad3 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -79,9 +79,9 @@ When generating a change file, follow these guidelines: 2. Write a brief but useful description with Nimble clients in mind. If making a major (breaking) change, explain what clients need to do to adopt it. The description can be plain text or [markdown](https://docs.github.com/en/get-started/writing-on-github/getting-started-with-writing-and-formatting-on-github/basic-writing-and-formatting-syntax), with newlines specified via `\n` if needed. 3. If you prefer not to expose your email address to the world, [configure GitHub to "Keep my email address private"](https://github.com/settings/emails) before generating the change file. -### NPM audit +### Dependency Review -The repository runs [`npm audit`](https://docs.npmjs.com/cli/v8/commands/npm-audit) to prevent submissions if any dependencies have known vulnerabilities. This can occur during on a PR that introduces a new dependency version or on an unrelated PR if a vulnerability was recently reported on an existing dependency. If this check fails, our options include: +The repository runs the [Dependency Review](https://github.com/actions/dependency-review-action) action to prevent submissions if any dependencies have known vulnerabilities. This can occur during on a PR that introduces a new dependency version or on an unrelated PR if a vulnerability was recently reported on an existing dependency. If this check fails, our options include: #### Vulnerabilities with fixes available @@ -93,7 +93,7 @@ The repository runs [`npm audit`](https://docs.npmjs.com/cli/v8/commands/npm-aud If a fix for the vulnerability isn't available or if it isn't practical to uptake the fix, our options include: 1. Remove the vulnerable dependency and find a different way to achieve the same functionality. -2. Temporarily use a more lenient [audit level](https://docs.npmjs.com/cli/v8/commands/npm-audit#audit-level) for this repository (e.g. allowing `low` or `moderate` vulnerabilities). We should ensure there is an issue on the dependency's repository asking them to fix the vulnerability and also file an issue against this repository to track fixing the vulnerability and restoring strict auditing. +2. Dismiss the alert in the [GitHub Security - Dependabot](https://github.com/ni/nimble/security/dependabot) dashboard, and document your rationale for doing so. We should ensure there is an issue on the dependency's repository asking them to fix the vulnerability and also file an issue against this repository to track fixing the vulnerability and restoring strict auditing. ### Chromatic visual component tests diff --git a/angular-workspace/package.json b/angular-workspace/package.json index 8850fcb683..7173fbc48e 100644 --- a/angular-workspace/package.json +++ b/angular-workspace/package.json @@ -58,7 +58,7 @@ "karma-jasmine": "^5.1.0", "karma-jasmine-html-reporter": "^2.0.0", "ng-packagr": "^15.2.2", - "playwright": "1.40.0", + "playwright": "1.42.0", "rollup": "^4.12.0", "typescript": "~4.9.5" } diff --git a/angular-workspace/projects/ni/nimble-angular/CHANGELOG.json b/angular-workspace/projects/ni/nimble-angular/CHANGELOG.json index c95bf7331b..43e44a26b9 100644 --- a/angular-workspace/projects/ni/nimble-angular/CHANGELOG.json +++ b/angular-workspace/projects/ni/nimble-angular/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/nimble-angular", "entries": [ + { + "date": "Mon, 25 Mar 2024 17:03:11 GMT", + "version": "20.5.3", + "tag": "@ni/nimble-angular_v20.5.3", + "comments": { + "patch": [ + { + "author": "beachball", + "package": "@ni/nimble-angular", + "comment": "Bump @ni/nimble-components to v23.0.1", + "commit": "not available" + } + ] + } + }, { "date": "Thu, 21 Mar 2024 17:13:38 GMT", "version": "20.5.2", diff --git a/angular-workspace/projects/ni/nimble-angular/CHANGELOG.md b/angular-workspace/projects/ni/nimble-angular/CHANGELOG.md index 3a4d8e308d..9f66bd06eb 100644 --- a/angular-workspace/projects/ni/nimble-angular/CHANGELOG.md +++ b/angular-workspace/projects/ni/nimble-angular/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/nimble-angular -This log was last generated on Thu, 21 Mar 2024 17:13:38 GMT and should not be manually modified. +This log was last generated on Mon, 25 Mar 2024 17:03:11 GMT and should not be manually modified. +## 20.5.3 + +Mon, 25 Mar 2024 17:03:11 GMT + +### Patches + +- Bump @ni/nimble-components to v23.0.1 + ## 20.5.2 Thu, 21 Mar 2024 17:13:38 GMT diff --git a/angular-workspace/projects/ni/nimble-angular/package.json b/angular-workspace/projects/ni/nimble-angular/package.json index b6db60197e..d98a826070 100644 --- a/angular-workspace/projects/ni/nimble-angular/package.json +++ b/angular-workspace/projects/ni/nimble-angular/package.json @@ -1,6 +1,6 @@ { "name": "@ni/nimble-angular", - "version": "20.5.2", + "version": "20.5.3", "description": "Angular components for the NI Nimble Design System", "scripts": { "invoke-publish": "cd ../../../ && npm run build:library && cd dist/ni/nimble-angular && npm publish" @@ -31,7 +31,7 @@ "@angular/forms": "^15.2.10", "@angular/localize": "^15.2.10", "@angular/router": "^15.2.10", - "@ni/nimble-components": "^23.0.0" + "@ni/nimble-components": "^23.0.1" }, "dependencies": { "tslib": "^2.2.0" diff --git a/package-lock.json b/package-lock.json index feef610ba6..3767bc84bf 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,7 +24,7 @@ "beachball": "^2.31.0", "cross-env": "^7.0.3", "patch-package": "^8.0.0", - "playwright": "1.40.0" + "playwright": "1.42.0" } }, "angular-workspace": { @@ -67,14 +67,14 @@ "karma-jasmine": "^5.1.0", "karma-jasmine-html-reporter": "^2.0.0", "ng-packagr": "^15.2.2", - "playwright": "1.40.0", + "playwright": "1.42.0", "rollup": "^4.12.0", "typescript": "~4.9.5" } }, "angular-workspace/projects/ni/nimble-angular": { "name": "@ni/nimble-angular", - "version": "20.5.2", + "version": "20.5.3", "license": "MIT", "dependencies": { "tslib": "^2.2.0" @@ -85,7 +85,7 @@ "@angular/forms": "^15.2.10", "@angular/localize": "^15.2.10", "@angular/router": "^15.2.10", - "@ni/nimble-components": "^23.0.0" + "@ni/nimble-components": "^23.0.1" } }, "node_modules/@11ty/dependency-tree": { @@ -26482,12 +26482,12 @@ } }, "node_modules/playwright": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.40.0.tgz", - "integrity": "sha512-gyHAgQjiDf1m34Xpwzaqb76KgfzYrhK7iih+2IzcOCoZWr/8ZqmdBw+t0RU85ZmfJMgtgAiNtBQ/KS2325INXw==", + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.42.0.tgz", + "integrity": "sha512-Ko7YRUgj5xBHbntrgt4EIw/nE//XBHOKVKnBjO1KuZkmkhlbgyggTe5s9hjqQ1LpN+Xg+kHsQyt5Pa0Bw5XpvQ==", "dev": true, "dependencies": { - "playwright-core": "1.40.0" + "playwright-core": "1.42.0" }, "bin": { "playwright": "cli.js" @@ -26500,9 +26500,9 @@ } }, "node_modules/playwright-core": { - "version": "1.40.0", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.40.0.tgz", - "integrity": "sha512-fvKewVJpGeca8t0ipM56jkVSU6Eo0RmFvQ/MaCQNDYm+sdvKkMBBWTE1FdeMqIdumRaXXjZChWHvIzCGM/tA/Q==", + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.42.0.tgz", + "integrity": "sha512-0HD9y8qEVlcbsAjdpBaFjmaTHf+1FeIddy8VJLeiqwhcNqGCBe4Wp2e8knpqiYbzxtxarxiXyNDw2cG8sCaNMQ==", "dev": true, "bin": { "playwright-core": "cli.js" @@ -33934,13 +33934,13 @@ "karma-jasmine": "^5.1.0", "karma-jasmine-html-reporter": "^2.0.0", "karma-spec-reporter": "^0.0.36", - "playwright": "1.40.0", + "playwright": "1.42.0", "typescript": "~4.9.5" } }, "packages/nimble-blazor": { "name": "@ni/nimble-blazor", - "version": "14.5.2", + "version": "14.5.3", "hasInstallScript": true, "license": "MIT", "devDependencies": { @@ -33951,7 +33951,7 @@ "@rollup/plugin-node-resolve": "^15.0.1", "cross-env": "^7.0.3", "glob": "^10.3.10", - "playwright": "1.40.0", + "playwright": "1.42.0", "rimraf": "^5.0.5", "rollup": "^4.12.0" } @@ -33976,7 +33976,7 @@ }, "packages/nimble-components": { "name": "@ni/nimble-components", - "version": "23.0.0", + "version": "23.0.1", "license": "MIT", "dependencies": { "@microsoft/fast-colors": "^5.3.1", @@ -34063,7 +34063,7 @@ "karma-spec-reporter": "^0.0.36", "karma-webkit-launcher": "^2.1.0", "karma-webpack": "^5.0.0", - "playwright": "1.40.0", + "playwright": "1.42.0", "prettier-eslint": "^16.3.0", "prettier-eslint-cli": "^8.0.1", "remark-gfm": "^3.0.1", @@ -34076,7 +34076,7 @@ "typescript": "~4.9.5", "webpack": "^5.75.0", "webpack-cli": "^5.0.1", - "webpack-dev-middleware": "^7.1.0" + "webpack-dev-middleware": "^7.0.0" }, "peerDependencies": { "apache-arrow": "^15.0.0" diff --git a/package.json b/package.json index 69f6114952..a0cde29a26 100644 --- a/package.json +++ b/package.json @@ -47,6 +47,6 @@ "beachball": "^2.31.0", "cross-env": "^7.0.3", "patch-package": "^8.0.0", - "playwright": "1.40.0" + "playwright": "1.42.0" } } diff --git a/packages/jasmine-parameterized/CHANGELOG.json b/packages/jasmine-parameterized/CHANGELOG.json index 62aadb0a18..b9f515edf9 100644 --- a/packages/jasmine-parameterized/CHANGELOG.json +++ b/packages/jasmine-parameterized/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/jasmine-parameterized", "entries": [ + { + "date": "Fri, 22 Mar 2024 16:18:25 GMT", + "version": "0.2.3", + "tag": "@ni/jasmine-parameterized_v0.2.3", + "comments": { + "none": [ + { + "author": "jattasNI@users.noreply.github.com", + "package": "@ni/jasmine-parameterized", + "commit": "559c12f4b5eaae8fdbd18c6c0d2ecff097b699d5", + "comment": "Update Playwright dev dependency to 1.42.0" + } + ] + } + }, { "date": "Tue, 12 Mar 2024 21:01:53 GMT", "version": "0.2.3", diff --git a/packages/jasmine-parameterized/package.json b/packages/jasmine-parameterized/package.json index 5683dbbc83..f4888edaea 100644 --- a/packages/jasmine-parameterized/package.json +++ b/packages/jasmine-parameterized/package.json @@ -51,7 +51,7 @@ "karma-jasmine": "^5.1.0", "karma-jasmine-html-reporter": "^2.0.0", "karma-spec-reporter": "^0.0.36", - "playwright": "1.40.0", + "playwright": "1.42.0", "typescript": "~4.9.5" } } diff --git a/packages/nimble-blazor/CHANGELOG.json b/packages/nimble-blazor/CHANGELOG.json index bb6c73b2d4..4f5282b62b 100644 --- a/packages/nimble-blazor/CHANGELOG.json +++ b/packages/nimble-blazor/CHANGELOG.json @@ -1,6 +1,21 @@ { "name": "@ni/nimble-blazor", "entries": [ + { + "date": "Fri, 22 Mar 2024 16:18:25 GMT", + "version": "14.5.2", + "tag": "@ni/nimble-blazor_v14.5.2", + "comments": { + "none": [ + { + "author": "jattasNI@users.noreply.github.com", + "package": "@ni/nimble-blazor", + "commit": "559c12f4b5eaae8fdbd18c6c0d2ecff097b699d5", + "comment": "Update Playwright dev dependency to 1.42.0" + } + ] + } + }, { "date": "Mon, 18 Mar 2024 17:12:34 GMT", "version": "14.5.0", diff --git a/packages/nimble-blazor/package.json b/packages/nimble-blazor/package.json index a496b2b43e..fc97e5c96e 100644 --- a/packages/nimble-blazor/package.json +++ b/packages/nimble-blazor/package.json @@ -1,6 +1,6 @@ { "name": "@ni/nimble-blazor", - "version": "14.5.2", + "version": "14.5.3", "description": "Blazor components for the NI Nimble Design System", "scripts": { "postinstall": "node build/generate-playwright-version-properties/source/index.js", @@ -48,7 +48,7 @@ "@rollup/plugin-node-resolve": "^15.0.1", "cross-env": "^7.0.3", "glob": "^10.3.10", - "playwright": "1.40.0", + "playwright": "1.42.0", "rimraf": "^5.0.5", "rollup": "^4.12.0" } diff --git a/packages/nimble-components/CHANGELOG.json b/packages/nimble-components/CHANGELOG.json index df4d30114b..f72608c8e3 100644 --- a/packages/nimble-components/CHANGELOG.json +++ b/packages/nimble-components/CHANGELOG.json @@ -1,6 +1,36 @@ { "name": "@ni/nimble-components", "entries": [ + { + "date": "Mon, 25 Mar 2024 17:03:11 GMT", + "version": "23.0.1", + "tag": "@ni/nimble-components_v23.0.1", + "comments": { + "patch": [ + { + "author": "33986780+munteannatan@users.noreply.github.com", + "package": "@ni/nimble-components", + "commit": "f56b73b45161a55b967dc03bbdd094a6527c814c", + "comment": "Created new hover event for the new diesTable api and changed the zoom event" + } + ] + } + }, + { + "date": "Fri, 22 Mar 2024 16:18:25 GMT", + "version": "23.0.0", + "tag": "@ni/nimble-components_v23.0.0", + "comments": { + "none": [ + { + "author": "jattasNI@users.noreply.github.com", + "package": "@ni/nimble-components", + "commit": "559c12f4b5eaae8fdbd18c6c0d2ecff097b699d5", + "comment": "Update Playwright dev dependency to 1.42.0" + } + ] + } + }, { "date": "Thu, 21 Mar 2024 17:13:38 GMT", "version": "23.0.0", diff --git a/packages/nimble-components/CHANGELOG.md b/packages/nimble-components/CHANGELOG.md index a3208751fb..4b8e71ac3a 100644 --- a/packages/nimble-components/CHANGELOG.md +++ b/packages/nimble-components/CHANGELOG.md @@ -1,9 +1,17 @@ # Change Log - @ni/nimble-components -This log was last generated on Thu, 21 Mar 2024 17:13:38 GMT and should not be manually modified. +This log was last generated on Mon, 25 Mar 2024 17:03:11 GMT and should not be manually modified. +## 23.0.1 + +Mon, 25 Mar 2024 17:03:11 GMT + +### Patches + +- Created new hover event for the new diesTable api and changed the zoom event ([ni/nimble@f56b73b](https://github.com/ni/nimble/commit/f56b73b45161a55b967dc03bbdd094a6527c814c)) + ## 23.0.0 Thu, 21 Mar 2024 17:13:38 GMT diff --git a/packages/nimble-components/package.json b/packages/nimble-components/package.json index d23d40c7e5..171e0ee8b9 100644 --- a/packages/nimble-components/package.json +++ b/packages/nimble-components/package.json @@ -1,6 +1,6 @@ { "name": "@ni/nimble-components", - "version": "23.0.0", + "version": "23.0.1", "description": "Styled web components for the NI Nimble Design System", "scripts": { "build": "npm run generate-icons && npm run generate-workers && npm run build-components && npm run bundle-components && npm run generate-scss && npm run build-storybook", @@ -151,7 +151,7 @@ "karma-spec-reporter": "^0.0.36", "karma-webkit-launcher": "^2.1.0", "karma-webpack": "^5.0.0", - "playwright": "1.40.0", + "playwright": "1.42.0", "prettier-eslint": "^16.3.0", "prettier-eslint-cli": "^8.0.1", "remark-gfm": "^3.0.1", diff --git a/packages/nimble-components/src/wafer-map/index.ts b/packages/nimble-components/src/wafer-map/index.ts index aed309664d..70c09e9b8d 100644 --- a/packages/nimble-components/src/wafer-map/index.ts +++ b/packages/nimble-components/src/wafer-map/index.ts @@ -10,19 +10,23 @@ import { template } from './template'; import { styles } from './styles'; import { DataManager } from './modules/data-manager'; import { RenderingModule } from './modules/rendering'; -import { EventCoordinator } from './modules/event-coordinator'; import { + HoverDie, HoverDieOpacity, WaferMapColorScale, WaferMapColorScaleMode, WaferMapDie, WaferMapOrientation, WaferMapOriginLocation, - WaferMapValidity + WaferMapValidity, + type WaferRequiredFields } from './types'; import { WaferMapUpdateTracker } from './modules/wafer-map-update-tracker'; import { WaferMapValidator } from './modules/wafer-map-validator'; -import { WorkerRenderer } from './modules/worker-renderer'; +import { WorkerRenderer } from './modules/experimental/worker-renderer'; +import { HoverHandler } from './modules/hover-handler'; +import { HoverHandler as ExperimentalHoverHandler } from './modules/experimental/hover-handler'; +import { ZoomHandler } from './modules/zoom-handler'; declare global { interface HTMLElementTagNameMap { @@ -33,12 +37,14 @@ declare global { /** * A nimble-styled WaferMap */ -export class WaferMap extends FoundationElement { +export class WaferMap< + T extends WaferRequiredFields = WaferRequiredFields +> extends FoundationElement { /** * @internal * needs to be initialized before the properties trigger changes */ - public readonly waferMapUpdateTracker = new WaferMapUpdateTracker(this); + public readonly waferMapUpdateTracker: WaferMapUpdateTracker = new WaferMapUpdateTracker(this.asRequiredFieldsWaferMap); @attr({ attribute: 'origin-location' }) public originLocation: WaferMapOriginLocation = WaferMapOriginLocation.bottomLeft; @@ -88,15 +94,23 @@ export class WaferMap extends FoundationElement { /** * @internal */ - public readonly dataManager = new DataManager(this); + public readonly dataManager: DataManager = new DataManager( + this.asRequiredFieldsWaferMap + ); + /** * @internal */ - public readonly mainRenderer = new RenderingModule(this); + public readonly mainRenderer = new RenderingModule( + this.asRequiredFieldsWaferMap + ); + /** * @internal */ - public readonly workerRenderer = new WorkerRenderer(this); + public readonly workerRenderer = new WorkerRenderer( + this.asRequiredFieldsWaferMap + ); @observable public renderer: RenderingModule | WorkerRenderer = this.mainRenderer; @@ -144,20 +158,29 @@ export class WaferMap extends FoundationElement { /** * @internal */ - @observable public hoverDie: WaferMapDie | undefined; + @observable public hoverDie: WaferMapDie | HoverDie | undefined; @observable public highlightedTags: string[] = []; @observable public dies: WaferMapDie[] = []; - @observable public diesTable: Table | undefined; + @observable public diesTable: Table | undefined; @observable public colorScale: WaferMapColorScale = { colors: [], values: [] }; - private readonly eventCoordinator = new EventCoordinator(this); + private readonly hoverHandler: HoverHandler = new HoverHandler( + this.asRequiredFieldsWaferMap + ); + + private readonly experimentalHoverHandler: ExperimentalHoverHandler = new ExperimentalHoverHandler(this.asRequiredFieldsWaferMap); + + private readonly zoomHandler: ZoomHandler = new ZoomHandler( + this.asRequiredFieldsWaferMap + ); + private readonly resizeObserver = this.createResizeObserver(); - private readonly waferMapValidator = new WaferMapValidator(this); + private readonly waferMapValidator: WaferMapValidator = new WaferMapValidator(this.asRequiredFieldsWaferMap); public get validity(): WaferMapValidity { return this.waferMapValidator.getValidity(); @@ -168,12 +191,18 @@ export class WaferMap extends FoundationElement { this.canvasContext = this.canvas.getContext('2d', { willReadFrequently: true })!; + this.hoverHandler.connect(); + this.experimentalHoverHandler.connect(); + this.zoomHandler.connect(); this.resizeObserver.observe(this); this.waferMapUpdateTracker.trackAll(); } public override disconnectedCallback(): void { super.disconnectedCallback(); + this.hoverHandler.disconnect(); + this.experimentalHoverHandler.disconnect(); + this.zoomHandler.disconnect(); this.resizeObserver.unobserve(this); } @@ -190,8 +219,12 @@ export class WaferMap extends FoundationElement { if (this.validity.invalidDiesTableSchema) { return; } + this.renderer = this.isExperimentalRenderer() + ? this.workerRenderer + : this.mainRenderer; if (this.waferMapUpdateTracker.requiresEventsUpdate) { - this.eventCoordinator.detachEvents(); + // zoom translateExtent needs to be recalculated when canvas size changes + this.zoomHandler.disconnect(); if (this.waferMapUpdateTracker.requiresContainerDimensionsUpdate) { this.dataManager.updateContainerDimensions(); this.renderer.updateSortedDiesAndDrawWafer(); @@ -211,12 +244,19 @@ export class WaferMap extends FoundationElement { } else if (this.waferMapUpdateTracker.requiresDrawnWaferUpdate) { this.renderer.drawWafer(); } - this.eventCoordinator.attachEvents(); + this.zoomHandler.connect(); } else if (this.waferMapUpdateTracker.requiresRenderHoverUpdate) { this.renderer.renderHover(); } } + /** + * @internal + */ + public isExperimentalRenderer(): boolean { + return this.diesTable !== undefined; + } + private validate(): void { this.waferMapValidator.validateGridDimensions(); this.waferMapValidator.validateDiesTableSchema(); @@ -291,17 +331,11 @@ export class WaferMap extends FoundationElement { private diesChanged(): void { this.waferMapUpdateTracker.track('dies'); - this.renderer = this.diesTable === undefined - ? this.mainRenderer - : this.workerRenderer; this.waferMapUpdateTracker.queueUpdate(); } private diesTableChanged(): void { this.waferMapUpdateTracker.track('dies'); - this.renderer = this.diesTable === undefined - ? this.mainRenderer - : this.workerRenderer; this.waferMapUpdateTracker.queueUpdate(); } @@ -330,6 +364,10 @@ export class WaferMap extends FoundationElement { this.waferMapUpdateTracker.track('hoverDie'); this.waferMapUpdateTracker.queueUpdate(); } + + private get asRequiredFieldsWaferMap(): WaferMap { + return this as WaferMap; + } } const nimbleWaferMap = WaferMap.compose({ diff --git a/packages/nimble-components/src/wafer-map/modules/data-manager.ts b/packages/nimble-components/src/wafer-map/modules/data-manager.ts index fb9fdbc3e9..b098683bfd 100644 --- a/packages/nimble-components/src/wafer-map/modules/data-manager.ts +++ b/packages/nimble-components/src/wafer-map/modules/data-manager.ts @@ -58,13 +58,13 @@ export class DataManager { return this.dataMap; } - private readonly computations; - private readonly prerendering; + private readonly computations: Computations; + private readonly prerendering: Prerendering; private dataMap!: Map; public constructor(private readonly wafermap: WaferMap) { this.computations = new Computations(wafermap); - this.prerendering = new Prerendering(wafermap, this); + this.prerendering = new Prerendering(wafermap); } public updateContainerDimensions(): void { diff --git a/packages/nimble-components/src/wafer-map/modules/event-coordinator.ts b/packages/nimble-components/src/wafer-map/modules/event-coordinator.ts deleted file mode 100644 index 420d401be5..0000000000 --- a/packages/nimble-components/src/wafer-map/modules/event-coordinator.ts +++ /dev/null @@ -1,47 +0,0 @@ -import type { WaferMapDie } from '../types'; -import { ZoomHandler } from './zoom-handler'; -import type { WaferMap } from '..'; -import { HoverHandler } from './hover-handler'; - -export interface EventCoordinatorCallbacks { - dieSelected: (die: WaferMapDie) => void; -} - -/** - * EventCoordinator deals with user interactions and events - */ -export class EventCoordinator { - private readonly zoomHandler; - private readonly hoverHandler; - public constructor(private readonly wafermap: WaferMap) { - this.zoomHandler = new ZoomHandler(wafermap); - this.hoverHandler = new HoverHandler(wafermap); - } - - public attachEvents(): void { - this.zoomHandler.createZoomBehavior(); - this.wafermap.addEventListener('mousemove', this.onMouseMove); - this.wafermap.addEventListener('mouseout', this.onMouseOut); - this.wafermap.canvas.addEventListener('wheel', this.onWheelMove, { - passive: false - }); - } - - public detachEvents(): void { - this.wafermap.removeEventListener('mousemove', this.onMouseMove); - this.wafermap.removeEventListener('mouseout', this.onMouseOut); - this.wafermap.canvas.removeEventListener('wheel', this.onWheelMove); - } - - private readonly onWheelMove = (event: Event): void => { - event.preventDefault(); - }; - - private readonly onMouseMove = (event: MouseEvent): void => { - this.hoverHandler.mousemove(event); - }; - - private readonly onMouseOut = (): void => { - this.hoverHandler.mouseout(); - }; -} diff --git a/packages/nimble-components/src/wafer-map/modules/experimental/hover-handler.ts b/packages/nimble-components/src/wafer-map/modules/experimental/hover-handler.ts new file mode 100644 index 0000000000..82339eebdc --- /dev/null +++ b/packages/nimble-components/src/wafer-map/modules/experimental/hover-handler.ts @@ -0,0 +1,98 @@ +import type { WaferMap } from '../..'; +import { PointCoordinates, WaferMapOriginLocation } from '../../types'; + +/** + * HoverHandler deals with user interactions and events like hovering + */ +export class HoverHandler { + public constructor(private readonly wafermap: WaferMap) {} + + /** + * @internal + */ + public connect(): void { + this.wafermap.addEventListener('mousemove', this.onMouseMove); + this.wafermap.addEventListener('mouseout', this.onMouseOut); + } + + /** + * @internal + */ + public disconnect(): void { + this.wafermap.removeEventListener('mousemove', this.onMouseMove); + this.wafermap.removeEventListener('mouseout', this.onMouseOut); + } + + /** + * @internal + * keep public for testing until data manager refactor + */ + public readonly onMouseMove = (event: MouseEvent): void => { + if (!this.wafermap.isExperimentalRenderer()) { + return; + } + // get original mouse position in case we are in zoom. + const invertedPoint = this.wafermap.transform.invert([ + event.offsetX, + event.offsetY + ]); + + // does not work yet until data manager will parse diesTable + const dieCoordinates = this.calculateDieCoordinates({ + x: invertedPoint[0], + y: invertedPoint[1] + }); + const colIndex = this.wafermap + .diesTable!.getChild('colIndex')! + .toArray(); + const rowIndex = this.wafermap + .diesTable!.getChild('rowIndex')! + .toArray(); + + // will replace iterating with arquero filtering after fixing errors + for (let i = 0; i < colIndex.length; i++) { + if ( + colIndex[i] === dieCoordinates.x + && rowIndex[i] === dieCoordinates.y + ) { + this.wafermap.hoverDie = { + index: i, + x: dieCoordinates.x, + y: dieCoordinates.y + }; + return; + } + } + this.wafermap.hoverDie = undefined; + }; + + private readonly onMouseOut = (_event: MouseEvent): void => { + this.wafermap.hoverDie = undefined; + }; + + private calculateDieCoordinates( + mousePosition: PointCoordinates + ): PointCoordinates { + const originLocation = this.wafermap.originLocation; + const xRoundFunction = originLocation === WaferMapOriginLocation.bottomLeft + || originLocation === WaferMapOriginLocation.topLeft + ? Math.floor + : Math.ceil; + const yRoundFunction = originLocation === WaferMapOriginLocation.bottomLeft + || originLocation === WaferMapOriginLocation.bottomRight + ? Math.floor + : Math.ceil; + // go to x and y scale to get the x,y values of the die. + const x = xRoundFunction( + this.wafermap.dataManager.invertedHorizontalScale( + mousePosition.x - this.wafermap.dataManager.margin.left + ) + ); + const y = yRoundFunction( + this.wafermap.dataManager.invertedVerticalScale( + mousePosition.y - this.wafermap.dataManager.margin.top + ) + ); + return { x, y }; + } +} diff --git a/packages/nimble-components/src/wafer-map/modules/worker-renderer.ts b/packages/nimble-components/src/wafer-map/modules/experimental/worker-renderer.ts similarity index 95% rename from packages/nimble-components/src/wafer-map/modules/worker-renderer.ts rename to packages/nimble-components/src/wafer-map/modules/experimental/worker-renderer.ts index 24dbcc8a73..5556c7bfe2 100644 --- a/packages/nimble-components/src/wafer-map/modules/worker-renderer.ts +++ b/packages/nimble-components/src/wafer-map/modules/experimental/worker-renderer.ts @@ -1,5 +1,5 @@ -import type { WaferMap } from '..'; -import { HoverDieOpacity } from '../types'; +import type { WaferMap } from '../..'; +import { HoverDieOpacity } from '../../types'; /** * Responsible for drawing the dies inside the wafer map, adding dieText and scaling the canvas diff --git a/packages/nimble-components/src/wafer-map/modules/hover-handler.ts b/packages/nimble-components/src/wafer-map/modules/hover-handler.ts index cab13191d6..393d7ba015 100644 --- a/packages/nimble-components/src/wafer-map/modules/hover-handler.ts +++ b/packages/nimble-components/src/wafer-map/modules/hover-handler.ts @@ -6,13 +6,33 @@ import { PointCoordinates, WaferMapOriginLocation } from '../types'; */ export class HoverHandler { public constructor(private readonly wafermap: WaferMap) {} - public mousemove(event: MouseEvent): void { + + /** + * @internal + */ + public connect(): void { + this.wafermap.addEventListener('mousemove', this.onMouseMove); + this.wafermap.addEventListener('mouseout', this.onMouseOut); + } + + /** + * @internal + */ + public disconnect(): void { + this.wafermap.removeEventListener('mousemove', this.onMouseMove); + this.wafermap.removeEventListener('mouseout', this.onMouseOut); + } + + private readonly onMouseMove = (event: MouseEvent): void => { + if (this.wafermap.isExperimentalRenderer()) { + return; + } const mousePosition: PointCoordinates = { x: event.offsetX, y: event.offsetY }; - if (!this.hoversOverDie(this.wafermap, mousePosition)) { + if (!this.hoversOverDie(mousePosition)) { this.wafermap.hoverDie = undefined; return; } @@ -22,23 +42,22 @@ export class HoverHandler { mousePosition.y ]); - const dieCoordinates = this.calculateDieCoordinates(this.wafermap, { + const dieCoordinates = this.calculateDieCoordinates({ x: invertedPoint[0], y: invertedPoint[1] }); this.wafermap.hoverDie = this.wafermap.dataManager.getWaferMapDie(dieCoordinates); - } + }; - public mouseout(): void { + private readonly onMouseOut = (_event: MouseEvent): void => { this.wafermap.hoverDie = undefined; - } + }; private calculateDieCoordinates( - wafermap: WaferMap, mousePosition: PointCoordinates ): PointCoordinates { - const originLocation = wafermap.originLocation; + const originLocation = this.wafermap.originLocation; const xRoundFunction = originLocation === WaferMapOriginLocation.bottomLeft || originLocation === WaferMapOriginLocation.topLeft ? Math.floor @@ -49,23 +68,20 @@ export class HoverHandler { : Math.ceil; // go to x and y scale to get the x,y values of the die. const x = xRoundFunction( - wafermap.dataManager.invertedHorizontalScale( - mousePosition.x - wafermap.dataManager.margin.left + this.wafermap.dataManager.invertedHorizontalScale( + mousePosition.x - this.wafermap.dataManager.margin.left ) ); const y = yRoundFunction( - wafermap.dataManager.invertedVerticalScale( - mousePosition.y - wafermap.dataManager.margin.top + this.wafermap.dataManager.invertedVerticalScale( + mousePosition.y - this.wafermap.dataManager.margin.top ) ); return { x, y }; } - private hoversOverDie( - wafermap: WaferMap, - mousePosition: PointCoordinates - ): boolean { - const rgba = wafermap.canvasContext.getImageData( + private hoversOverDie(mousePosition: PointCoordinates): boolean { + const rgba = this.wafermap.canvasContext.getImageData( mousePosition.x, mousePosition.y, 1, diff --git a/packages/nimble-components/src/wafer-map/modules/prerendering.ts b/packages/nimble-components/src/wafer-map/modules/prerendering.ts index 9d4db977d0..85f464d548 100644 --- a/packages/nimble-components/src/wafer-map/modules/prerendering.ts +++ b/packages/nimble-components/src/wafer-map/modules/prerendering.ts @@ -8,7 +8,6 @@ import type { WaferMapDie } from '../types'; import type { WaferMap } from '..'; -import type { DataManager } from './data-manager'; /** * Prerendering prepares render-ready dies data to be used by the rendering module @@ -34,14 +33,11 @@ export class Prerendering { private readonly emptyDieColor = 'rgba(218,223,236,1)'; private readonly nanDieColor = 'rgba(122,122,122,1)'; - public constructor( - private readonly wafermap: WaferMap, - private readonly dataManager: Readonly - ) {} + public constructor(private readonly wafermap: WaferMap) {} public updateLabelsFontSize(): void { this._labelsFontSize = this.calculateLabelsFontSize( - this.dataManager.dieDimensions, + this.wafermap.dataManager.dieDimensions, this.wafermap.maxCharacters ); this.updateDiesRenderInfo(); @@ -61,10 +57,10 @@ export class Prerendering { } private computeDieRenderInfo(die: WaferMapDie): DieRenderInfo | null { - const margin = this.dataManager.margin; + const margin = this.wafermap.dataManager.margin; - const scaledX = this.dataManager.horizontalScale(die.x); - const scaledY = this.dataManager.verticalScale(die.y); + const scaledX = this.wafermap.dataManager.horizontalScale(die.x); + const scaledY = this.wafermap.dataManager.verticalScale(die.y); if (scaledX === undefined || scaledY === undefined) { return null; diff --git a/packages/nimble-components/src/wafer-map/modules/wafer-map-validator.ts b/packages/nimble-components/src/wafer-map/modules/wafer-map-validator.ts index 9ef38a00a0..6788f50149 100644 --- a/packages/nimble-components/src/wafer-map/modules/wafer-map-validator.ts +++ b/packages/nimble-components/src/wafer-map/modules/wafer-map-validator.ts @@ -25,10 +25,10 @@ export class WaferMapValidator { public validateGridDimensions(): boolean { this.invalidGridDimensions = false; if ( - typeof this.wafermap.gridMinX === 'undefined' - && typeof this.wafermap.gridMaxX === 'undefined' - && typeof this.wafermap.gridMinY === 'undefined' - && typeof this.wafermap.gridMaxY === 'undefined' + this.wafermap.gridMinX === undefined + && this.wafermap.gridMaxX === undefined + && this.wafermap.gridMinY === undefined + && this.wafermap.gridMaxY === undefined ) { this.invalidGridDimensions = false; } else if ( @@ -49,38 +49,20 @@ export class WaferMapValidator { if (this.wafermap.diesTable === undefined) { this.invalidDiesTableSchema = false; } else { - const colIndexField = this.wafermap.diesTable.schema.fields.findIndex( - f => f.name === 'colIndex' - ); - const rowIndexField = this.wafermap.diesTable.schema.fields.findIndex( - f => f.name === 'rowIndex' - ); - const valueField = this.wafermap.diesTable.schema.fields.findIndex( - f => f.name === 'value' - ); + const fields = this.wafermap.diesTable.schema.fields; + const colField = fields.find(field => field.name === 'colIndex'); + const rowField = fields.find(field => field.name === 'rowIndex'); + const valueField = fields.find(field => field.name === 'value'); if ( - this.wafermap.diesTable.numCols < 3 - || colIndexField === -1 - || rowIndexField === -1 - || valueField === -1 - || !DataType.isInt( - this.wafermap.diesTable.schema.fields[colIndexField]!.type - ) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - || this.wafermap.diesTable.schema.fields[colIndexField]!.type - .bitWidth !== 32 - || !DataType.isInt( - this.wafermap.diesTable.schema.fields[rowIndexField]!.type - ) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - || this.wafermap.diesTable.schema.fields[rowIndexField]!.type - .bitWidth !== 32 - || !DataType.isFloat( - this.wafermap.diesTable.schema.fields[valueField]!.type - ) - // eslint-disable-next-line @typescript-eslint/no-unsafe-member-access - || this.wafermap.diesTable.schema.fields[valueField]!.type - .precision !== Precision.DOUBLE + !colField + || !rowField + || !valueField + || !DataType.isInt(colField.type) + || colField.type.bitWidth !== 32 + || !DataType.isInt(rowField.type) + || rowField.type.bitWidth !== 32 + || !DataType.isFloat(valueField.type) + || valueField.type.precision !== Precision.DOUBLE ) { this.invalidDiesTableSchema = true; } diff --git a/packages/nimble-components/src/wafer-map/modules/zoom-handler.ts b/packages/nimble-components/src/wafer-map/modules/zoom-handler.ts index 38a82d89b1..79635b403c 100644 --- a/packages/nimble-components/src/wafer-map/modules/zoom-handler.ts +++ b/packages/nimble-components/src/wafer-map/modules/zoom-handler.ts @@ -1,11 +1,5 @@ import { select } from 'd3-selection'; -import { - zoom, - ZoomBehavior, - zoomIdentity, - ZoomTransform, - zoomTransform -} from 'd3-zoom'; +import { zoom, ZoomTransform } from 'd3-zoom'; import type { WaferMap } from '..'; interface ZoomEvent { @@ -16,61 +10,44 @@ interface ZoomEvent { * ZoomHandler deals with user interactions and events like zooming */ export class ZoomHandler { - private zoomTransform: ZoomTransform = zoomIdentity; - private readonly minScale = 1.1; - private readonly minExtentPoint: [number, number] = [-100, -100]; - private readonly extentPadding = 100; - private zoomBehavior!: ZoomBehavior; + private readonly scaleExtent: [number, number] = [1, 100]; + private readonly minExtentPoint: [number, number] = [0, 0]; public constructor(private readonly wafermap: WaferMap) {} - public createZoomBehavior(): void { - this.zoomBehavior = zoom() - .scaleExtent([ - 1.1, - this.getZoomMax( - this.wafermap.canvasWidth * this.wafermap.canvasHeight, - this.wafermap.dataManager.containerDimensions.width - * this.wafermap.dataManager.containerDimensions.height - ) - ]) + /** + * @internal + */ + public connect(): void { + this.createZoomBehavior(); + this.wafermap.addEventListener('wheel', this.onWheelMove, { + passive: false + }); + } + + /** + * @internal + */ + public disconnect(): void { + zoom().on('zoom', null)(select(this.wafermap as Element)); + this.wafermap.removeEventListener('wheel', this.onWheelMove); + } + + private createZoomBehavior(): void { + zoom() + .scaleExtent(this.scaleExtent) .translateExtent([ this.minExtentPoint, - [ - this.wafermap.canvasWidth + this.extentPadding, - this.wafermap.canvasHeight + this.extentPadding - ] + [this.wafermap.canvasWidth, this.wafermap.canvasHeight] ]) - .filter((event: Event) => { - const transform = zoomTransform(this.wafermap.canvas); - const filterEval = transform.k >= this.minScale || event.type === 'wheel'; - return filterEval; - }) .on('zoom', (event: ZoomEvent) => { // D3 will automatically remove existing handlers when adding new ones // See: https://github.com/d3/d3-zoom/blob/v3.0.0/README.md#zoom_on - this.rescale(event); - }); - - this.zoomBehavior(select(this.wafermap.canvas as Element)); + this.wafermap.transform = event.transform; + })(select(this.wafermap as Element)); } - private rescale(event: ZoomEvent): void { - const transform = event.transform; - if (transform.k === this.minScale) { - this.zoomTransform = zoomIdentity; - this.zoomBehavior.transform( - select(this.wafermap.canvas as Element), - zoomIdentity - ); - } else { - this.zoomTransform = transform; - } - - this.wafermap.transform = this.zoomTransform; - } - - private getZoomMax(canvasArea: number, dataArea: number): number { - return Math.ceil((dataArea / canvasArea) * 100); - } + private readonly onWheelMove = (event: Event): void => { + event.preventDefault(); + }; } diff --git a/packages/nimble-components/src/wafer-map/tests/computations.spec.ts b/packages/nimble-components/src/wafer-map/tests/computations.spec.ts index deb673b81c..0f0ead89ef 100644 --- a/packages/nimble-components/src/wafer-map/tests/computations.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/computations.spec.ts @@ -1,4 +1,3 @@ -import type { WaferMap } from '..'; import { Computations } from '../modules/computations'; import { Margin, WaferMapOriginLocation } from '../types'; import { getWaferMapMockComputations, getWaferMapDies } from './utilities'; @@ -20,7 +19,7 @@ describe('Wafermap Computations module', () => { 100, 100 ); - computationsModule = new Computations(waferMock as WaferMap); + computationsModule = new Computations(waferMock); computationsModule.updateContainerDimensions(); }); @@ -70,7 +69,7 @@ describe('Wafermap Computations module', () => { 200, 100 ); - computationsModule = new Computations(waferMock as WaferMap); + computationsModule = new Computations(waferMock); computationsModule.updateContainerDimensions(); }); @@ -114,7 +113,7 @@ describe('Wafermap Computations module', () => { 100, 100 ); - computationsModule = new Computations(waferMock as WaferMap); + computationsModule = new Computations(waferMock); computationsModule.updateContainerDimensions(); }); @@ -136,7 +135,7 @@ describe('Wafermap Computations module', () => { 100, 100 ); - computationsModule = new Computations(waferMock as WaferMap); + computationsModule = new Computations(waferMock); computationsModule.updateContainerDimensions(); }); @@ -158,7 +157,7 @@ describe('Wafermap Computations module', () => { 100, 100 ); - computationsModule = new Computations(waferMock as WaferMap); + computationsModule = new Computations(waferMock); computationsModule.updateContainerDimensions(); }); @@ -180,7 +179,7 @@ describe('Wafermap Computations module', () => { 100, 100 ); - computationsModule = new Computations(waferMock as WaferMap); + computationsModule = new Computations(waferMock); computationsModule.updateContainerDimensions(); }); diff --git a/packages/nimble-components/src/wafer-map/tests/data-generator.ts b/packages/nimble-components/src/wafer-map/tests/data-generator.ts index fff32e67e5..77cc8efa71 100644 --- a/packages/nimble-components/src/wafer-map/tests/data-generator.ts +++ b/packages/nimble-components/src/wafer-map/tests/data-generator.ts @@ -154,6 +154,6 @@ export const generateWaferTableData = ( return tableFromArrays({ colIndex: Int32Array.from(colIndex), rowIndex: Int32Array.from(rowIndex), - value: Float32Array.from(value) + value: Float64Array.from(value) }); }; diff --git a/packages/nimble-components/src/wafer-map/tests/hover-handler.spec.ts b/packages/nimble-components/src/wafer-map/tests/hover-handler.spec.ts new file mode 100644 index 0000000000..7bee0ae2aa --- /dev/null +++ b/packages/nimble-components/src/wafer-map/tests/hover-handler.spec.ts @@ -0,0 +1,114 @@ +import { zoomIdentity } from 'd3-zoom'; +import { tableFromArrays } from 'apache-arrow'; +import { html } from '@microsoft/fast-element'; +import { parameterizeSpec } from '@ni/jasmine-parameterized'; +import { HoverHandler } from '../modules/experimental/hover-handler'; +import { WaferMapOriginLocation } from '../types'; +import { + getDataManagerMockForHover, + getScaleQuantile, + getWaferMapMockHover +} from './utilities'; +import type { WaferMap } from '..'; +import { processUpdates } from '../../testing/async-helpers'; +import { Fixture, fixture } from '../../utilities/tests/fixture'; + +async function setup(): Promise> { + return fixture(html`
`); +} + +describe('HoverHandler', () => { + let element: HTMLDivElement; + let connect: () => Promise; + let disconnect: () => Promise; + let hoverHandler: HoverHandler; + let waferMock: WaferMap; + + beforeEach(async () => { + ({ element, connect, disconnect } = await setup()); + await connect(); + waferMock = getWaferMapMockHover( + tableFromArrays({ + colIndex: Int32Array.from([1, 2, 3]), + rowIndex: Int32Array.from([1, 2, 3]), + value: Float64Array.from([1, 2, 3]) + }), + zoomIdentity, + WaferMapOriginLocation.bottomLeft, + undefined, + getDataManagerMockForHover( + { left: 0, right: 0, top: 0, bottom: 0 }, + getScaleQuantile([1, 11], [1, 2, 3, 4]), + getScaleQuantile([1, 11], [1, 2, 3, 4]) + ), + true + ); + }); + + afterEach(async () => { + await disconnect(); + }); + + const testCases = [ + { + name: WaferMapOriginLocation.bottomLeft, + expectedDie: { index: 1, x: 2, y: 2 } + }, + { + name: WaferMapOriginLocation.topLeft, + expectedDie: { index: 1, x: 2, y: 2 } + }, + { + name: WaferMapOriginLocation.bottomRight, + expectedDie: { index: 1, x: 2, y: 2 } + }, + { + name: WaferMapOriginLocation.topRight, + expectedDie: { index: 1, x: 2, y: 2 } + } + ] as const; + + parameterizeSpec(testCases, (spec, name, value) => { + spec( + `will return the expected index when mouse moved in range from ${name}`, + () => { + waferMock.originLocation = value.name; + hoverHandler = new HoverHandler(waferMock); + element.addEventListener('mousemove', event => hoverHandler.onMouseMove(event)); + element.dispatchEvent( + new MouseEvent('mousemove', { + clientX: 4, + clientY: 4 + }) + ); + processUpdates(); + expect(waferMock.hoverDie).toEqual(value.expectedDie); + } + ); + }); + + const undefinedTestCases = [ + { name: WaferMapOriginLocation.bottomLeft, expectedDie: undefined }, + { name: WaferMapOriginLocation.topLeft, expectedDie: undefined }, + { name: WaferMapOriginLocation.bottomRight, expectedDie: undefined }, + { name: WaferMapOriginLocation.topRight, expectedDie: undefined } + ] as const; + parameterizeSpec(undefinedTestCases, (spec, name, value) => { + spec( + `will return undefined when mouse moved out of range from ${name}`, + () => { + waferMock.originLocation = value.name; + hoverHandler = new HoverHandler(waferMock); + element.addEventListener('mousemove', event => hoverHandler.onMouseMove(event)); + element.dispatchEvent( + new MouseEvent('mousemove', { + clientX: 15, + clientY: 15 + }) + ); + processUpdates(); + expect(waferMock.hoverDie).toEqual(value.expectedDie); + } + ); + }); +}); diff --git a/packages/nimble-components/src/wafer-map/tests/prerendering.coloring.spec.ts b/packages/nimble-components/src/wafer-map/tests/prerendering.coloring.spec.ts index 5cfb169a65..2b93f87e82 100644 --- a/packages/nimble-components/src/wafer-map/tests/prerendering.coloring.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/prerendering.coloring.spec.ts @@ -1,5 +1,3 @@ -import type { WaferMap } from '..'; -import type { DataManager } from '../modules/data-manager'; import { Prerendering } from '../modules/prerendering'; import { WaferMapColorScaleMode } from '../types'; import { @@ -28,6 +26,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: ['red'], values: ['1'] }, @@ -35,18 +39,10 @@ describe('Wafermap Prerendering module', () => { colorScaleMode, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -70,6 +66,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { @@ -80,18 +82,10 @@ describe('Wafermap Prerendering module', () => { colorScaleMode, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -115,6 +109,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { @@ -125,18 +125,10 @@ describe('Wafermap Prerendering module', () => { colorScaleMode, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -167,6 +159,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: ['red'], values: ['1'] }, @@ -174,18 +172,10 @@ describe('Wafermap Prerendering module', () => { colorScaleMode, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -209,6 +199,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { @@ -219,18 +215,10 @@ describe('Wafermap Prerendering module', () => { colorScaleMode, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -260,6 +248,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + getScaleBand([0, 1], [0, 100]), + getScaleBand([0, 1], [0, 100]) + ); const waferMock = getWaferMapMockPrerendering( [ { @@ -273,18 +267,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - getScaleBand([0, 1], [0, 100]), - getScaleBand([0, 1], [0, 100]) - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -308,6 +294,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + getScaleBand([0, 1], [0, 100]), + getScaleBand([0, 1], [0, 100]) + ); const waferMock = getWaferMapMockPrerendering( [ { @@ -321,18 +313,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - getScaleBand([0, 1], [0, 100]), - getScaleBand([0, 1], [0, 100]) - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -356,6 +340,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: ['red'], values: [] }, @@ -363,18 +353,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.ordinal, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -405,6 +387,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: ['red'], values: [] }, @@ -412,18 +400,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.ordinal, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); diff --git a/packages/nimble-components/src/wafer-map/tests/prerendering.labeling.spec.ts b/packages/nimble-components/src/wafer-map/tests/prerendering.labeling.spec.ts index 60c98db5b8..fb3d5ffdf7 100644 --- a/packages/nimble-components/src/wafer-map/tests/prerendering.labeling.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/prerendering.labeling.spec.ts @@ -1,5 +1,3 @@ -import type { WaferMap } from '..'; -import type { DataManager } from '../modules/data-manager'; import { Prerendering } from '../modules/prerendering'; import { WaferMapColorScaleMode } from '../types'; import { @@ -24,6 +22,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: [], values: [] }, @@ -31,18 +35,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -68,6 +64,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: [], values: [] }, @@ -75,18 +77,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -106,6 +100,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: [], values: [] }, @@ -113,18 +113,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -148,6 +140,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: [], values: [] }, @@ -155,18 +153,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -191,6 +181,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: [], values: [] }, @@ -198,18 +194,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -236,6 +224,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDiesAsNaN(), { colors: [], values: [] }, @@ -243,18 +237,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -281,6 +267,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDiesAsFloats(), { colors: [], values: [] }, @@ -288,18 +280,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -330,6 +314,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 0, right: 0, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: [], values: [] }, @@ -337,18 +327,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); diff --git a/packages/nimble-components/src/wafer-map/tests/prerendering.positioning.spec.ts b/packages/nimble-components/src/wafer-map/tests/prerendering.positioning.spec.ts index a54606c526..8b65558c50 100644 --- a/packages/nimble-components/src/wafer-map/tests/prerendering.positioning.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/prerendering.positioning.spec.ts @@ -1,5 +1,3 @@ -import type { WaferMap } from '..'; -import type { DataManager } from '../modules/data-manager'; import { Prerendering } from '../modules/prerendering'; import { WaferMapColorScaleMode } from '../types'; import { @@ -23,6 +21,12 @@ describe('Wafermap Prerendering module', () => { const margin = { top: 20, right: 10, bottom: 0, left: 0 }; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: [], values: [] }, @@ -30,18 +34,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -83,6 +79,12 @@ describe('Wafermap Prerendering module', () => { const highlightedTags: string[] = []; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + horizontalScale, + defaultVerticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: [], values: [] }, @@ -90,18 +92,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - horizontalScale, - defaultVerticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); @@ -132,6 +126,12 @@ describe('Wafermap Prerendering module', () => { const highlightedTags: string[] = []; beforeEach(() => { + const dataManagerMock = getDataManagerMock( + dieDimensions, + margin, + defaultHorizontalScale, + verticalScale + ); const waferMock = getWaferMapMockPrerendering( getWaferMapDies(), { colors: [], values: [] }, @@ -139,18 +139,10 @@ describe('Wafermap Prerendering module', () => { WaferMapColorScaleMode.linear, dieLabelsHidden, dieLabelsSuffix, - maxCharacters - ); - const dataManagerMock = getDataManagerMock( - dieDimensions, - margin, - defaultHorizontalScale, - verticalScale - ); - prerenderingModule = new Prerendering( - waferMock as WaferMap, - dataManagerMock as DataManager + maxCharacters, + dataManagerMock ); + prerenderingModule = new Prerendering(waferMock); prerenderingModule.updateLabelsFontSize(); }); diff --git a/packages/nimble-components/src/wafer-map/tests/sets.ts b/packages/nimble-components/src/wafer-map/tests/sets.ts index 3b26320e4c..80089b35ee 100644 --- a/packages/nimble-components/src/wafer-map/tests/sets.ts +++ b/packages/nimble-components/src/wafer-map/tests/sets.ts @@ -105,7 +105,7 @@ export const wafermapDiesTableSets: Table[] = [ tableFromArrays({ colIndex: Int32Array.from([0, 1, 1, 1, 2, 2, 2, 2, 2, 3, 3, 3, 4]), rowIndex: Int32Array.from([2, 2, 1, 3, 2, 1, 0, 3, 4, 2, 1, 3, 2]), - value: Float32Array.from([ + value: Float64Array.from([ 14.24, 76.43, 44.63, 67.93, 72.71, 79.04, 26.49, 37.79, 59.82, 52.9, 98.5, 20.83, 62.8 ]), diff --git a/packages/nimble-components/src/wafer-map/tests/utilities.ts b/packages/nimble-components/src/wafer-map/tests/utilities.ts index f654e3b9bf..f30aa122dc 100644 --- a/packages/nimble-components/src/wafer-map/tests/utilities.ts +++ b/packages/nimble-components/src/wafer-map/tests/utilities.ts @@ -1,7 +1,9 @@ -import { ScaleBand, scaleBand } from 'd3-scale'; +import { ScaleBand, ScaleQuantile, scaleBand, scaleQuantile } from 'd3-scale'; import type { Table } from 'apache-arrow'; +import type { ZoomTransform } from 'd3-zoom'; import { Dimensions, + HoverDie, Margin, WaferMapColorScale, WaferMapColorScaleMode, @@ -64,6 +66,12 @@ export function getScaleBand( return scaleBand().domain(domain).range(range); } +export function getScaleQuantile( + domain: number[] = [], + range: number[] = [] +): ScaleQuantile { + return scaleQuantile().domain(domain).range(range); +} export const defaultHorizontalScale = scaleBand() .domain([2, 3, 4, 5, 6]) .range([2, 7]); @@ -77,16 +85,39 @@ export function getDataManagerMock( margin: Margin, horizontalScale: ScaleBand = getScaleBand([], []), verticalScale: ScaleBand = getScaleBand([], []) -): Pick< +): DataManager { + const dataManagerMock: Pick< DataManager, 'horizontalScale' | 'verticalScale' | 'dieDimensions' | 'margin' - > { - return { + > = { horizontalScale, verticalScale, dieDimensions, margin }; + return dataManagerMock as DataManager; +} + +export function getDataManagerMockForHover( + margin: Margin, + invertedHorizontalScale: ScaleQuantile = getScaleQuantile( + [], + [] + ), + invertedVerticalScale: ScaleQuantile = getScaleQuantile( + [], + [] + ) +): DataManager { + const dataManagerMock: Pick< + DataManager, + 'invertedHorizontalScale' | 'invertedVerticalScale' | 'margin' + > = { + invertedHorizontalScale, + invertedVerticalScale, + margin + }; + return dataManagerMock as DataManager; } export function getWaferMapMockPrerendering( @@ -96,8 +127,10 @@ export function getWaferMapMockPrerendering( colorScaleMode: WaferMapColorScaleMode = WaferMapColorScaleMode.linear, dieLabelsHidden = true, dieLabelsSuffix = '', - maxCharacters = 4 -): Pick< + maxCharacters = 4, + dataManager = {} as DataManager +): WaferMap { + const waferMapMock: Pick< WaferMap, | 'dies' | 'colorScale' @@ -106,18 +139,46 @@ export function getWaferMapMockPrerendering( | 'dieLabelsHidden' | 'dieLabelsSuffix' | 'maxCharacters' - > { - return { + | 'dataManager' + > = { dies, colorScale, highlightedTags, colorScaleMode, dieLabelsHidden, dieLabelsSuffix, - maxCharacters + maxCharacters, + dataManager }; + return waferMapMock as WaferMap; } +export function getWaferMapMockHover( + diesTable: Table, + transform: ZoomTransform, + originLocation: WaferMapOriginLocation, + hoverDie: HoverDie | undefined, + dataManager: DataManager, + isExperimentalRenderer: boolean +): WaferMap { + const waferMapMock: Pick< + WaferMap, + | 'diesTable' + | 'transform' + | 'originLocation' + | 'hoverDie' + | 'dataManager' + | 'isExperimentalRenderer' + > = { + diesTable, + transform, + originLocation, + hoverDie, + dataManager, + isExperimentalRenderer: () => isExperimentalRenderer + }; + return waferMapMock as WaferMap; +} export function getWaferMapMockComputations( dies: WaferMapDie[] = getWaferMapDies(), originLocation: WaferMapOriginLocation, @@ -127,17 +188,18 @@ export function getWaferMapMockComputations( invalidGridDimensions: false, invalidDiesTableSchema: false } -): Pick< +): WaferMap { + const waferMapMock: Pick< WaferMap, 'dies' | 'originLocation' | 'canvasWidth' | 'canvasHeight' | 'validity' - > { - return { + > = { dies, originLocation, canvasWidth, canvasHeight, validity }; + return waferMapMock as WaferMap; } export function getWaferMapMockValidator( @@ -146,15 +208,16 @@ export function getWaferMapMockValidator( gridMinY: number | undefined, gridMaxY: number | undefined, diesTable: Table | undefined = undefined -): Pick< +): WaferMap { + const waferMapMock: Pick< WaferMap, 'gridMinX' | 'gridMaxX' | 'gridMinY' | 'gridMaxY' | 'diesTable' - > { - return { + > = { gridMinX, gridMaxX, gridMinY, gridMaxY, diesTable }; + return waferMapMock as WaferMap; } diff --git a/packages/nimble-components/src/wafer-map/tests/wafer-map-validator.spec.ts b/packages/nimble-components/src/wafer-map/tests/wafer-map-validator.spec.ts index 732833fa9a..659fbee23c 100644 --- a/packages/nimble-components/src/wafer-map/tests/wafer-map-validator.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/wafer-map-validator.spec.ts @@ -1,5 +1,4 @@ import { Table, tableFromArrays } from 'apache-arrow'; -import type { WaferMap } from '..'; import { WaferMapValidator } from '../modules/wafer-map-validator'; import { getWaferMapMockValidator } from './utilities'; @@ -13,7 +12,7 @@ describe('Wafermap Validator module', () => { undefined, undefined ); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateGridDimensions(); expect(waferMapValidator.isValid()).toBeTrue(); @@ -21,7 +20,7 @@ describe('Wafermap Validator module', () => { it('with equal grid dimensions should be valid', () => { const waferMock = getWaferMapMockValidator(0, 0, 0, 0); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateGridDimensions(); expect(waferMapValidator.isValid()).toBeTrue(); @@ -29,7 +28,7 @@ describe('Wafermap Validator module', () => { it('with positive grid dimensions should be valid', () => { const waferMock = getWaferMapMockValidator(1, 2, 1, 2); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateGridDimensions(); expect(waferMapValidator.isValid()).toBeTrue(); @@ -37,7 +36,7 @@ describe('Wafermap Validator module', () => { it('with negative grid dimensions should be valid', () => { const waferMock = getWaferMapMockValidator(-2, -1, -2, -1); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateGridDimensions(); expect(waferMapValidator.isValid()).toBeTrue(); @@ -45,7 +44,7 @@ describe('Wafermap Validator module', () => { it('with one undefined grid dimension should not be valid', () => { const waferMock = getWaferMapMockValidator(0, 0, 0, undefined); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateGridDimensions(); expect(waferMapValidator.isValid()).toBeFalse(); @@ -53,7 +52,7 @@ describe('Wafermap Validator module', () => { it('with impossible grid dimension should not be valid', () => { const waferMock = getWaferMapMockValidator(1, -1, 1, -1); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateGridDimensions(); expect(waferMapValidator.getValidity()).toEqual({ @@ -71,7 +70,7 @@ describe('Wafermap Validator module', () => { undefined, undefined ); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateDiesTableSchema(); expect(waferMapValidator.isValid()).toBeTrue(); }); @@ -88,7 +87,7 @@ describe('Wafermap Validator module', () => { value: Float64Array.from([]) }) ); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateDiesTableSchema(); expect(waferMapValidator.isValid()).toBeTrue(); @@ -106,7 +105,7 @@ describe('Wafermap Validator module', () => { value: Float32Array.from([]) }) ); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateDiesTableSchema(); expect(waferMapValidator.isValid()).toBeFalse(); @@ -124,7 +123,7 @@ describe('Wafermap Validator module', () => { value: Float64Array.from([]) }) ); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateDiesTableSchema(); expect(waferMapValidator.isValid()).toBeFalse(); @@ -142,7 +141,7 @@ describe('Wafermap Validator module', () => { value: Int32Array.from([]) }) ); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateDiesTableSchema(); expect(waferMapValidator.isValid()).toBeFalse(); @@ -156,7 +155,7 @@ describe('Wafermap Validator module', () => { undefined, new Table() ); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateDiesTableSchema(); expect(waferMapValidator.isValid()).toBeFalse(); @@ -172,7 +171,7 @@ describe('Wafermap Validator module', () => { rowIndex: Int32Array.from([]) }) ); - waferMapValidator = new WaferMapValidator(waferMock as WaferMap); + waferMapValidator = new WaferMapValidator(waferMock); waferMapValidator.validateDiesTableSchema(); expect(waferMapValidator.isValid()).toBeFalse(); diff --git a/packages/nimble-components/src/wafer-map/tests/wafer-map.spec.ts b/packages/nimble-components/src/wafer-map/tests/wafer-map.spec.ts index f811df6fce..e443b632ee 100644 --- a/packages/nimble-components/src/wafer-map/tests/wafer-map.spec.ts +++ b/packages/nimble-components/src/wafer-map/tests/wafer-map.spec.ts @@ -9,7 +9,7 @@ import { WaferMapOriginLocation } from '../types'; import { RenderingModule } from '../modules/rendering'; -import { WorkerRenderer } from '../modules/worker-renderer'; +import { WorkerRenderer } from '../modules/experimental/worker-renderer'; async function setup(): Promise> { return fixture(html``); @@ -88,24 +88,12 @@ describe('WaferMap', () => { expect(spy).toHaveBeenCalledTimes(1); }); - it('will use RenderingModule after dies change', () => { - element.dies = [{ x: 1, y: 1, value: '1' }]; - processUpdates(); - expect(element.renderer instanceof RenderingModule).toBeTrue(); - }); - it('will update once after diesTable change', () => { element.diesTable = new Table(); processUpdates(); expect(spy).toHaveBeenCalledTimes(1); }); - it('will use WorkerRenderer after diesTable change', () => { - element.diesTable = new Table(); - processUpdates(); - expect(element.renderer instanceof WorkerRenderer).toBeTrue(); - }); - it('will update once after colorScale changes', () => { element.colorScale = { colors: ['red', 'red'], values: ['1', '1'] }; processUpdates(); @@ -158,6 +146,28 @@ describe('WaferMap', () => { renderHoverSpy = spyOn(element.workerRenderer, 'renderHover'); }); + it('will use RenderingModule after dies change', () => { + element.dies = [{ x: 1, y: 1, value: '1' }]; + processUpdates(); + expect(element.renderer instanceof RenderingModule).toBeTrue(); + }); + + it('will use WorkerRenderer after supported diesTable change', () => { + element.diesTable = tableFromArrays({ + colIndex: Int32Array.from([]), + rowIndex: Int32Array.from([]), + value: Float64Array.from([]) + }); + processUpdates(); + expect(element.renderer instanceof WorkerRenderer).toBeTrue(); + }); + + it('will use RenderingModule after unsupported diesTable change', () => { + element.diesTable = new Table(); + processUpdates(); + expect(element.renderer instanceof RenderingModule).toBeTrue(); + }); + it('will call renderHover after supported diesTable change', () => { element.diesTable = tableFromArrays({ colIndex: Int32Array.from([]), @@ -191,7 +201,7 @@ describe('WaferMap', () => { }); it('will zoom in the wafer-map', () => { - element.canvas.dispatchEvent( + element.dispatchEvent( new WheelEvent('wheel', { deltaY: -2, deltaMode: -1 }) ); processUpdates(); @@ -200,7 +210,7 @@ describe('WaferMap', () => { }); it('will zoom out to identity', () => { - element.canvas.dispatchEvent( + element.dispatchEvent( new WheelEvent('wheel', { deltaY: -2, deltaMode: -1 }) ); @@ -208,7 +218,7 @@ describe('WaferMap', () => { const zoomedValue = getTransform(); expect(zoomedValue).not.toEqual(initialValue); - element.canvas.dispatchEvent( + element.dispatchEvent( new WheelEvent('wheel', { deltaY: 2, deltaMode: -1 }) ); @@ -218,7 +228,7 @@ describe('WaferMap', () => { }); it('will not zoom out when at identity', () => { - element.canvas.dispatchEvent( + element.dispatchEvent( new WheelEvent('wheel', { deltaY: 2, deltaMode: -1 }) ); processUpdates(); @@ -258,7 +268,7 @@ describe('WaferMap', () => { expect(initialHeight).toBe(460); expect(initialWidth).toBe(460); - element.canvas.dispatchEvent( + element.dispatchEvent( new WheelEvent('wheel', { deltaY: -2, deltaMode: -1 }) ); processUpdates(); @@ -277,7 +287,7 @@ describe('WaferMap', () => { processUpdates(); const initialTransform = element.hoverTransform; expect(initialTransform).not.toEqual(''); - element.canvas.dispatchEvent( + element.dispatchEvent( new WheelEvent('wheel', { deltaY: -2, deltaMode: -1 }) ); processUpdates(); diff --git a/packages/nimble-components/src/wafer-map/tests/wafer-map.stories.ts b/packages/nimble-components/src/wafer-map/tests/wafer-map.stories.ts index 2cd7f02974..c0b82ce309 100644 --- a/packages/nimble-components/src/wafer-map/tests/wafer-map.stories.ts +++ b/packages/nimble-components/src/wafer-map/tests/wafer-map.stories.ts @@ -81,7 +81,7 @@ const getDiesSet = ( )!; break; default: - returnedValue = [] as WaferMapDie[]; + returnedValue = []; } return returnedValue; }; @@ -133,7 +133,7 @@ const getHighlightedTags = (setName: string, sets: string[][]): string[] => { returnedValue = sets[3]!; break; default: - returnedValue = [] as string[]; + returnedValue = []; break; } return returnedValue; diff --git a/packages/nimble-components/src/wafer-map/types.ts b/packages/nimble-components/src/wafer-map/types.ts index cac887b0a0..7193593c4f 100644 --- a/packages/nimble-components/src/wafer-map/types.ts +++ b/packages/nimble-components/src/wafer-map/types.ts @@ -1,3 +1,5 @@ +import type { Float64, Int32 } from 'apache-arrow'; + export const WaferMapOriginLocation = { bottomLeft: 'bottom-left', bottomRight: 'bottom-right', @@ -43,6 +45,12 @@ export interface WaferMapDie { tags?: string[]; } +export interface HoverDie { + index: number; + x: number; + y: number; +} + export interface WaferMapColorScale { colors: string[]; values: string[]; @@ -79,3 +87,16 @@ export interface WaferMapValidity extends ValidityObject { readonly invalidGridDimensions: boolean; readonly invalidDiesTableSchema: boolean; } + +// Apache arrow probably should not be using a Record and index types on TypeMap +// because in strict checking they end up required. +// See: https://github.com/apache/arrow/issues/12663#issuecomment-1088244575 +// We can work around that issue by using a type alias instead of an interface +// Where index signatures are looser. +// See: https://github.com/microsoft/TypeScript/issues/15300#issuecomment-1317901527 +// eslint-disable-next-line @typescript-eslint/consistent-type-definitions +export type WaferRequiredFields = { + colIndex: Int32, + rowIndex: Int32, + value: Float64 +};