diff --git a/packages/datagrid/package.json b/packages/datagrid/package.json index e893bb261..4421746cb 100644 --- a/packages/datagrid/package.json +++ b/packages/datagrid/package.json @@ -26,8 +26,24 @@ "api": "api-extractor run --local --verbose", "build": "npm run build:src && rollup -c", "build:src": "tsc --build", + "build:test": "npm run clean:test && tsc --build tests && cd tests && rollup -c", "clean": "rimraf ./lib && rimraf *.tsbuildinfo && rimraf ./types && rimraf ./dist", + "clean:test": "rimraf tests/lib tests/tsconfig.tsbuildinfo", "minimize": "terser dist/index.js -c -m --source-map \"content='dist/index.js.map',url='index.min.js.map'\" -o dist/index.min.js", + "test": "npm run test:firefox-headless", + "test:chrome": "npm run test:nobrowser -- --browsers=Chrome", + "test:chrome-headless": "npm run test:nobrowser -- --browsers=ChromeHeadless", + "test:debug": "npm run test:debug:firefox", + "test:debug:chrome": "npm run test:debug:nobrowser -- --browsers=Chrome", + "test:debug:chrome-headless": "npm run test:debug:nobrowser -- --browsers=ChromeHeadless", + "test:debug:firefox": "npm run test:debug:nobrowser -- --browsers=Firefox", + "test:debug:firefox-headless": "npm run test:debug:nobrowser -- --browsers=FirefoxHeadless", + "test:debug:nobrowser": "cd tests && karma start --singleRun=false --debug=true --browserNoActivityTimeout=10000000 --browserDisconnectTimeout=10000000", + "test:firefox": "npm run test:nobrowser -- --browsers=Firefox", + "test:firefox-headless": "npm run test:nobrowser -- --browsers=FirefoxHeadless", + "test:webkit": "cd tests && karma start --browsers=Webkit", + "test:webkit-headless": "cd tests && karma start --browsers=WebkitHeadless", + "test:nobrowser": "cd tests && karma start", "watch": "tsc --build --watch" }, "typedoc": { @@ -50,6 +66,17 @@ "@microsoft/api-extractor": "^7.6.0", "@rollup/plugin-commonjs": "^24.0.0", "@rollup/plugin-node-resolve": "^15.0.1", + "@types/chai": "^3.4.35", + "@types/mocha": "^2.2.39", + "chai": "^4.3.4", + "karma": "^6.3.4", + "karma-chrome-launcher": "^3.1.0", + "karma-firefox-launcher": "^2.1.1", + "karma-mocha": "^2.0.1", + "karma-mocha-reporter": "^2.2.5", + "karma-webkit-launcher": "^1.0.2", + "mocha": "^9.0.3", + "playwright": "^1.29.0", "postcss": "^8.4.14", "rimraf": "^3.0.2", "rollup": "^3.9.1", diff --git a/packages/datagrid/tests/karma.conf.js b/packages/datagrid/tests/karma.conf.js new file mode 100644 index 000000000..82380ec18 --- /dev/null +++ b/packages/datagrid/tests/karma.conf.js @@ -0,0 +1,24 @@ +/* + * Copyright (c) Jupyter Development Team. + * Distributed under the terms of the Modified BSD License. + */ + +process.env.FIREFOX_BIN = require('playwright').firefox.executablePath(); +process.env.FIREFOX_HEADLESS_BIN = process.env.FIREFOX_BIN; +process.env.WEBKIT_BIN = require('playwright').webkit.executablePath(); +process.env.WEBKIT_HEADLESS_BIN = process.env.WEBKIT_BIN; + +module.exports = function (config) { + config.set({ + basePath: '.', + frameworks: ['mocha'], + reporters: ['mocha'], + files: ['lib/bundle.test.js'], + port: 9876, + colors: true, + singleRun: true, + browserNoActivityTimeout: 30000, + failOnEmptyTestSuite: false, + logLevel: config.LOG_INFO + }); +}; diff --git a/packages/datagrid/tests/rollup.config.mjs b/packages/datagrid/tests/rollup.config.mjs new file mode 100644 index 000000000..10d911526 --- /dev/null +++ b/packages/datagrid/tests/rollup.config.mjs @@ -0,0 +1,8 @@ +/* + * Copyright (c) Jupyter Development Team. + * Distributed under the terms of the Modified BSD License. + */ + +import { createRollupTestConfig } from '@lumino/buildutils'; +const rollupConfig = createRollupTestConfig(); +export default rollupConfig; diff --git a/packages/datagrid/tests/src/index.spec.ts b/packages/datagrid/tests/src/index.spec.ts new file mode 100644 index 000000000..c7ff3ba4d --- /dev/null +++ b/packages/datagrid/tests/src/index.spec.ts @@ -0,0 +1,4 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. + +import './textrenderer.spec'; diff --git a/packages/datagrid/tests/src/textrenderer.spec.ts b/packages/datagrid/tests/src/textrenderer.spec.ts new file mode 100644 index 000000000..efd481d65 --- /dev/null +++ b/packages/datagrid/tests/src/textrenderer.spec.ts @@ -0,0 +1,117 @@ +// Copyright (c) Jupyter Development Team. +// Distributed under the terms of the Modified BSD License. +import { expect } from 'chai'; + +import { CellRenderer, GraphicsContext, TextRenderer } from '@lumino/datagrid'; + +class LoggingGraphicsContext extends GraphicsContext { + fillText(text: string, x: number, y: number, maxWidth?: number): void { + super.fillText(text, x, y, maxWidth); + this.texts.push(text); + } + + texts: string[] = []; +} + +describe('@lumino/datagrid', () => { + let gc: LoggingGraphicsContext; + const defaultCellConfig: CellRenderer.CellConfig = { + x: 0, + y: 0, + width: 100, + height: 20, + row: 0, + column: 0, + region: 'body', + value: '', + metadata: {} + }; + beforeEach(() => { + const canvas = document.createElement('canvas'); + const context = canvas.getContext('2d')!; + gc = new LoggingGraphicsContext(context); + }); + describe('TextRenderer', () => { + describe('drawText()', () => { + it('should right-elide long strings', () => { + const renderer = new TextRenderer({ + elideDirection: 'right', + font: '12px Arial' + }); + renderer.drawText(gc, { + ...defaultCellConfig, + width: 100, + value: 'this text exceeds 100px' + }); + expect(gc.texts.pop()).to.eq('this text exce…'); + }); + + it('should left-elide long strings', () => { + const renderer = new TextRenderer({ + elideDirection: 'left', + font: '12px Arial' + }); + renderer.drawText(gc, { + ...defaultCellConfig, + width: 100, + value: 'this text exceeds 100px' + }); + // Pixel calculations differ between Firefox and Chrome, either is good. + expect(gc.texts.pop()).to.be.oneOf(['…xceeds 100px', '…ceeds 100px']); + }); + + it('should not elide if eliding is disabled', () => { + const renderer = new TextRenderer({ + elideDirection: 'none', + font: '12px Arial' + }); + renderer.drawText(gc, { + ...defaultCellConfig, + width: 100, + value: 'this text exceeds 100px' + }); + expect(gc.texts.pop()).to.eq('this text exceeds 100px'); + }); + + it('should wrap text', () => { + const renderer = new TextRenderer({ + elideDirection: 'none', + wrapText: true, + font: '12px Arial' + }); + renderer.drawText(gc, { + ...defaultCellConfig, + width: 100, + value: 'this text exceeds 100px' + }); + expect(gc.texts.pop()).to.eq('exceeds 100px'); + expect(gc.texts.pop()).to.eq('this text'); + }); + + it('should not break up Unicode surrogate characters (left)', () => { + const renderer = new TextRenderer({ + elideDirection: 'left', + font: '12px Arial' + }); + renderer.drawText(gc, { + ...defaultCellConfig, + width: 45, + value: '📦📦📦' + }); + expect(gc.texts.pop()).to.eq('…📦'); + }); + it('should not break up Unicode surrogate characters (right)', () => { + const renderer = new TextRenderer({ + elideDirection: 'right', + font: '12px Arial' + }); + renderer.drawText(gc, { + ...defaultCellConfig, + width: 45, + value: '📦📦📦' + }); + expect(gc.texts.pop()).to.eq('📦…'); + }); + }); + }); +}); diff --git a/packages/datagrid/tests/tsconfig.json b/packages/datagrid/tests/tsconfig.json new file mode 100644 index 000000000..d2de12617 --- /dev/null +++ b/packages/datagrid/tests/tsconfig.json @@ -0,0 +1,10 @@ +{ + "extends": "../../../tsconfigbase", + "compilerOptions": { + "lib": ["DOM", "ES2018"], + "outDir": "lib", + "rootDir": "src", + "types": ["chai", "mocha"] + }, + "include": ["src/*"] +} diff --git a/yarn.lock b/yarn.lock index 125f67c95..ed06d91f7 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1205,6 +1205,17 @@ __metadata: "@microsoft/api-extractor": ^7.6.0 "@rollup/plugin-commonjs": ^24.0.0 "@rollup/plugin-node-resolve": ^15.0.1 + "@types/chai": ^3.4.35 + "@types/mocha": ^2.2.39 + chai: ^4.3.4 + karma: ^6.3.4 + karma-chrome-launcher: ^3.1.0 + karma-firefox-launcher: ^2.1.1 + karma-mocha: ^2.0.1 + karma-mocha-reporter: ^2.2.5 + karma-webkit-launcher: ^1.0.2 + mocha: ^9.0.3 + playwright: ^1.29.0 postcss: ^8.4.14 rimraf: ^3.0.2 rollup: ^3.9.1