Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,17 @@ jobs:
with:
node-version: ${{ matrix.node-version }}

- name: npm install, build, and test
- name: npm install and build
run: |
npm install
npm run build --if-present
npm test
env:
CI: true

- name: Install Playwright browsers
run: npx playwright install --with-deps chromium

- name: Run tests
run: npm test
env:
CI: true
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,6 @@ npm-debug.*
.idea
coverage
lib
test-results/
playwright-report/
package-lock.json
45 changes: 0 additions & 45 deletions __tests__/index.spec.js

This file was deleted.

29 changes: 0 additions & 29 deletions __tests__/issue-17.spec.js

This file was deleted.

26 changes: 0 additions & 26 deletions __tests__/unbind.spec.js

This file was deleted.

28 changes: 0 additions & 28 deletions __tests__/utils.js

This file was deleted.

2 changes: 1 addition & 1 deletion dist/size-sensor.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

18 changes: 2 additions & 16 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
"main": "lib/index.js",
"types": "index.d.ts",
"scripts": {
"debug": "cross-env NODE_ENV=babel cross-env DEBUG_MODE=1 jest",
"test": "cross-env NODE_ENV=babel jest",
"test": "playwright test",
"build:umd": "rimraf ./dist && cross-env NODE_ENV=rollup rollup -c",
"build:lib": "rimraf ./lib && cross-env NODE_ENV=babel babel src -d lib",
"build": "npm run build:umd && npm run build:lib && limit-size"
Expand All @@ -33,29 +32,16 @@
"@babel/cli": "^7.6.0",
"@babel/core": "^7.6.0",
"@babel/preset-env": "^7.6.0",
"babel-jest": "^24.9.0",
"@playwright/test": "^1.58.0",
"babel-plugin-version": "^0.2.1",
"cross-env": "^5.1.3",
"jest": "^24.9.0",
"jest-electron": "^0.1.6",
"limit-size": "^0.1.2",
"rimraf": "^2.6.2",
"rollup": "^1.21.4",
"rollup-plugin-babel": "^4.3.3",
"rollup-plugin-node-resolve": "^5.2.0",
"rollup-plugin-uglify": "^6.0.3"
},
"jest": {
"runner": "jest-electron/runner",
"testEnvironment": "jest-electron/environment",
"collectCoverage": true,
"collectCoverageFrom": [
"src/**/*.{js,jsx}",
"!**/node_modules/**",
"!**/vendor/**"
],
"testRegex": "/__tests__/.*\\.spec\\.jsx?$"
},
"author": "hustcc",
"license": "ISC",
"bugs": {
Expand Down
21 changes: 21 additions & 0 deletions playwright.config.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { defineConfig, devices } from '@playwright/test';

export default defineConfig({
testDir: './tests',
testMatch: '**/*.spec.mjs',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
trace: 'on-first-retry',
},

projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
],
});
93 changes: 93 additions & 0 deletions tests/index.spec.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import { test, expect } from '@playwright/test';
import { readFileSync } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Read the built UMD bundle
const sizeSensorBundle = readFileSync(path.join(__dirname, '../dist/size-sensor.min.js'), 'utf8');

test.describe('size-sensor', () => {
test('export', async ({ page }) => {
// Load the size-sensor library
await page.setContent('<html><body></body></html>');
await page.addScriptTag({ content: sizeSensorBundle });

// Test exports
const hasExports = await page.evaluate(() => {
const { bind, clear, ver } = window.sizeSensor;
return {
bindIsFunction: typeof bind === 'function',
clearIsFunction: typeof clear === 'function',
verExists: typeof ver === 'string' && ver.length > 0
};
});

expect(hasExports.bindIsFunction).toBe(true);
expect(hasExports.clearIsFunction).toBe(true);
expect(hasExports.verExists).toBe(true);
});

test('demo', async ({ page }) => {
// Create a page with the demo setup
await page.setContent(`
<html>
<head>
<style>
#wrapper {
position: relative;
height: 400px;
background-color: #8bcdaf
}

#size-indicator {
position: absolute;
right: 4px;
bottom: 4px;
font-size: 10px;
color: black;
}
</style>
</head>
<body>
<div id="wrapper">
<div id="size-indicator"></div>
</div>
</body>
</html>
`);

// Load the size-sensor library
await page.addScriptTag({ content: sizeSensorBundle });

// Bind the sensor and verify it works
await page.evaluate(() => {
const { bind } = window.sizeSensor;
const indicator = document.getElementById('size-indicator');
const wrapper = document.getElementById('wrapper');

const cb = ele => {
const size = getComputedStyle(ele);
indicator.innerHTML = size.width + ' x ' + size.height;
indicator.style.color = 'red';

setTimeout(() => {
indicator.style.color = 'black';
}, 500);
};

// bind an element, when size changed, do cb function
bind(wrapper, cb);
});

// Verify the binding was successful
const hasSensorId = await page.evaluate(() => {
const wrapper = document.getElementById('wrapper');
return wrapper.getAttribute('size-sensor-id') !== null;
});

expect(hasSensorId).toBe(true);
});
});
75 changes: 75 additions & 0 deletions tests/issue-17.spec.mjs
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
import { test, expect } from '@playwright/test';
import { readFileSync } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';

const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Read the built UMD bundle
const sizeSensorBundle = readFileSync(path.join(__dirname, '../dist/size-sensor.min.js'), 'utf8');

test.describe('#17', () => {
test('memory leak', async ({ page }) => {
await page.setContent('<html><body><div id="wrapper"></div></body></html>');
await page.addScriptTag({ content: sizeSensorBundle });

// Create two bindings on the same element
await page.evaluate(() => {
const { bind } = window.sizeSensor;
const wrapper = document.getElementById('wrapper');

window.unbind1 = bind(wrapper, () => {});
window.unbind2 = bind(wrapper, () => {});
});

// Get the sensor ID
const sensorId = await page.evaluate(() => {
const wrapper = document.getElementById('wrapper');
return wrapper.getAttribute('size-sensor-id');
});

// Verify that a sensor was created
expect(sensorId).not.toBeNull();

// Verify that only one sensor object element exists (for ResizeObserver fallback)
let sensorObjectCount = await page.evaluate(() => {
const wrapper = document.getElementById('wrapper');
return wrapper.querySelectorAll('.size-sensor-object').length;
});

// Should be 0 or 1 (depends on if ResizeObserver is available)
expect(sensorObjectCount).toBeLessThanOrEqual(1);

// Call first unbind
await page.evaluate(() => {
window.unbind1();
});

// Verify sensor is still attached (because unbind2 still references it)
let stillHasSensorId = await page.evaluate(() => {
const wrapper = document.getElementById('wrapper');
return wrapper.getAttribute('size-sensor-id') !== null;
});
expect(stillHasSensorId).toBe(true);

// Call second unbind
await page.evaluate(() => {
window.unbind2();
});

// Verify sensor is now removed
const finalSensorId = await page.evaluate(() => {
const wrapper = document.getElementById('wrapper');
return wrapper.getAttribute('size-sensor-id');
});
expect(finalSensorId).toBeNull();

// Verify sensor object is also removed
sensorObjectCount = await page.evaluate(() => {
const wrapper = document.getElementById('wrapper');
return wrapper.querySelectorAll('.size-sensor-object').length;
});
expect(sensorObjectCount).toBe(0);
});
});
Loading