Skip to content

Commit 2ac36e3

Browse files
committed
chore: add unit tests and clean up dependencies
1 parent 673f009 commit 2ac36e3

File tree

17 files changed

+5563
-76
lines changed

17 files changed

+5563
-76
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,19 +15,19 @@ jobs:
1515
fail-fast: false
1616
matrix:
1717
os: [ ubuntu-latest ]
18-
node-version: [ 16 ]
18+
node-version: [ 20 ]
1919
steps:
2020
- name: Checkout Git Source
21-
uses: actions/checkout@v3
21+
uses: actions/checkout@v4
2222

2323
- name: Setup Node.js
24-
uses: actions/setup-node@v3
24+
uses: actions/setup-node@v4
2525
with:
2626
node-version: ${{ matrix.node-version }}
2727

2828
- name: Install dependencies
2929
run: |
30-
npm i npm@6 -g
30+
npm i npm@10 -g
3131
npm i
3232
3333
- name: Continuous integration
@@ -36,6 +36,6 @@ jobs:
3636
npm run test
3737
3838
- name: Code coverage
39-
uses: codecov/codecov-action@v3.0.0
39+
uses: codecov/codecov-action@v3
4040
with:
4141
token: ${{ secrets.CODECOV_TOKEN }}

.husky/pre-commit

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
npm run lint

.mocharc.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
module.exports = {
2+
reporter: 'spec',
3+
require: './test/unit/mock-setup.js',
4+
spec: ['test/unit/*.test.js'],
5+
};

.nycrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"reporter": ["lcov", "text"]
3+
}

AGENTS.md

Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
# AGENTS.md - Development Guide
2+
3+
This document provides guidelines for agents working on the electron-windows codebase.
4+
5+
## Project Overview
6+
7+
electron-windows is an Electron module for managing multiple windows gracefully. It provides window creation, retrieval by name/ID, state persistence, and loading views.
8+
9+
## Commands
10+
11+
### Development
12+
```bash
13+
pnpm run dev # Launch Electron demo app
14+
```
15+
16+
### Testing
17+
```bash
18+
pnpm test # Run unit tests with nyc coverage
19+
pnpm run test:e2e # Run end-to-end tests with Playwright
20+
```
21+
22+
To run a **single test file**:
23+
```bash
24+
npx mocha test/unit/electron-windows.test.js
25+
```
26+
27+
To run a **single test**:
28+
```bash
29+
npx mocha test/unit/electron-windows.test.js --grep "should create window with default options"
30+
```
31+
32+
### Linting
33+
```bash
34+
pnpm run lint # Run ESLint with auto-fix
35+
```
36+
37+
## Code Style Guidelines
38+
39+
### General
40+
- Language: JavaScript (ES2018), CommonJS modules
41+
- Always use `'use strict';` at the top of every file
42+
- Use 2-space indentation
43+
44+
### Imports/Exports
45+
- Use CommonJS: `const X = require('path')` and `module.exports = X`
46+
- Order: built-in modules first, then external packages, then local files
47+
- Empty line between groups
48+
49+
```javascript
50+
'use strict';
51+
52+
const fs = require('fs');
53+
const path = require('path');
54+
const _ = require('lodash');
55+
const { BrowserWindow } = require('electron');
56+
const windowStateKeeper = require('electron-window-state');
57+
58+
const MyClass = require('./my-class');
59+
```
60+
61+
### Naming Conventions
62+
- **Classes**: PascalCase (e.g., `WindowsManager`)
63+
- **Methods/variables**: camelCase (e.g., `createWindow`, `windowOptions`)
64+
- **Constants**: SCREAMING_SNAKE_CASE (e.g., `DEFAULT_WIDTH`)
65+
- **Private methods**: prefix with underscore (e.g., `_setGlobalUserAgent`)
66+
- **Files**: kebab-case (e.g., `electron-windows.js`)
67+
68+
### Types and JSDoc
69+
- This project does not use TypeScript
70+
- Use JSDoc comments for public APIs (though `valid-jsdoc` is disabled)
71+
- Document params and return values
72+
73+
```javascript
74+
/**
75+
* Creates a new window.
76+
* @param {Object} options - Window configuration
77+
* @param {string} [options.name='anonymous'] - Window identifier
78+
* @returns {BrowserWindow} The created window
79+
*/
80+
```
81+
82+
### Error Handling
83+
- Use `assert` for tests
84+
- Return early on error conditions
85+
- Check for destroyed windows before operations
86+
87+
```javascript
88+
if (window.isDestroyed()) {
89+
return;
90+
}
91+
```
92+
93+
### Best Practices
94+
- Always check if Electron objects are destroyed before using them:
95+
```javascript
96+
if (window && !window.isDestroyed()) { ... }
97+
if (webContents && !webContents.isDestroyed()) { ... }
98+
```
99+
- Use lodash utilities (already a dependency): `_.pick`, `_.debounce`, etc.
100+
- Avoid arrow functions for methods that need `this` binding
101+
102+
## Architecture
103+
104+
- **Main entry**: `index.js` exports from `lib/electron-windows.js`
105+
- **Core class**: `WindowsManager` in `lib/electron-windows.js`
106+
- **Tests**: `test/unit/` for unit tests, `test/e2e/` for E2E tests
107+
- **Mock setup**: `test/unit/mock-setup.js` provides Electron mocks
108+
109+
## Testing Patterns
110+
111+
- Use Mocha's `describe`/`it` structure
112+
- Use `beforeEach` to reset mocks
113+
- Use Node's `assert` module for assertions
114+
115+
```javascript
116+
const assert = require('assert');
117+
const WindowsManager = require('../../lib/electron-windows');
118+
119+
describe('WindowsManager', () => {
120+
beforeEach(() => {
121+
require('./mock-setup').reset();
122+
});
123+
124+
describe('create()', () => {
125+
it('should create window with default options', () => {
126+
const manager = new WindowsManager();
127+
const window = manager.create({});
128+
assert.strictEqual(window._name, 'anonymous');
129+
});
130+
});
131+
});
132+
```

CLAUDE.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# CLAUDE.md
2+
3+
See [AGENTS.md](AGENTS.md) for project guidelines and code style documentation.

README.md

Lines changed: 85 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -17,70 +17,112 @@
1717
[download-image]: https://img.shields.io/npm/dm/electron-windows.svg
1818
[download-url]: https://npmjs.org/package/electron-windows
1919

20-
> Manage multiple windows of Electron gracefully and provides powerful features.
20+
> Manage multiple windows of Electron gracefully and provide powerful features.
2121
22-
<!-- GITCONTRIBUTOR_START -->
23-
24-
## Contributors
25-
26-
|[<img src="https://avatars.githubusercontent.com/u/1011681?v=4" width="100px;"/><br/><sub><b>xudafeng</b></sub>](https://github.com/xudafeng)<br/>|[<img src="https://avatars.githubusercontent.com/u/17586742?v=4" width="100px;"/><br/><sub><b>sriting</b></sub>](https://github.com/sriting)<br/>|[<img src="https://avatars.githubusercontent.com/u/52845048?v=4" width="100px;"/><br/><sub><b>snapre</b></sub>](https://github.com/snapre)<br/>|[<img src="https://avatars.githubusercontent.com/u/12660278?v=4" width="100px;"/><br/><sub><b>ColaDaddyz</b></sub>](https://github.com/ColaDaddyz)<br/>|[<img src="https://avatars.githubusercontent.com/u/30524126?v=4" width="100px;"/><br/><sub><b>z0gSh1u</b></sub>](https://github.com/z0gSh1u)<br/>|[<img src="https://avatars.githubusercontent.com/u/4081746?v=4" width="100px;"/><br/><sub><b>zlyi</b></sub>](https://github.com/zlyi)<br/>|
27-
| :---: | :---: | :---: | :---: | :---: | :---: |
28-
[<img src="https://avatars.githubusercontent.com/u/50158871?v=4" width="100px;"/><br/><sub><b>moshangqi</b></sub>](https://github.com/moshangqi)<br/>
29-
30-
This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Fri Apr 25 2025 11:40:35 GMT+0800`.
31-
32-
<!-- GITCONTRIBUTOR_END -->
33-
34-
## Installment
22+
## Installation
3523

3624
```bash
3725
$ npm i electron-windows --save
3826
```
3927

4028
## Demo
4129

42-
![](./sceenshot.png)
30+
![](./screenshot.png)
4331

44-
## APIs
45-
46-
### init
32+
## Quick Start
4733

4834
```javascript
49-
const WindowManager = require('electron-windows');
50-
const windowManager = new WindowManager();
51-
```
35+
const WindowManager = require('electron-windows')
5236

53-
### create
37+
const windowManager = new WindowManager()
5438

55-
```javascript
56-
const { app } = require('electron');
57-
const winRef = windowManager.create({
58-
name: 'window1',
59-
loadingView: {
60-
url: '',
61-
},
39+
// Create a window
40+
const mainWindow = windowManager.create({
41+
name: 'main',
6242
browserWindow: {
6343
width: 800,
6444
height: 600,
65-
titleBarStyle: 'hidden',
66-
title: 'demo',
67-
show: false,
68-
webPreferences: {
69-
nodeIntegration: app.isDev,
70-
webSecurity: true,
71-
webviewTag: true,
72-
},
7345
},
74-
openDevTools: true,
75-
storageKey: 'storage-filename', // optional. The name of file. Support storage of window state
76-
storagePath: app.getPath('userData'), // optional. The path of file, only used when storageKey is not empty
77-
});
46+
})
47+
48+
// Get window by name
49+
const theWindow = windowManager.get('main')
50+
51+
// Get window by id
52+
const theWindowToo = windowManager.getById(mainWindow.id)
53+
54+
// Get all windows
55+
const all = windowManager.getAll()
7856
```
7957

80-
## TODO
58+
## API Reference
59+
60+
### `new WindowManager()`
61+
62+
Creates a new WindowManager instance.
63+
64+
### `windowManager.create(options)`
65+
66+
Creates and manages a new BrowserWindow.
67+
68+
- **options** `Object` - Configuration for the window:
69+
- **name** `string` - Window identifier, used by `get()`. Default: `'anonymous'`
70+
- **browserWindow** `Object` - [Electron BrowserWindow options](https://www.electronjs.org/docs/latest/api/browser-window)
71+
- **loadingView** `Object` - Loading view configuration:
72+
- **url** `string` - URL to show while main content loads
73+
- **openDevTools** `boolean` - Auto open DevTools when window is ready. Default: `false`
74+
- **preventOriginClose** `boolean` - Prevent window from closing, need manually close. Default: `false`
75+
- **preventOriginNavigate** `boolean` - Prevent webContents navigation. Default: `false`
76+
- **storageKey** `string` - Save/restore window position and size using `electron-window-state`
77+
- **storagePath** `string` - Custom storage path for window state file
78+
- **globalUserAgent** `string` - Custom User-Agent for all `loadURL` calls in this window
79+
80+
Returns: `BrowserWindow`
81+
82+
### `windowManager.get(name)`
83+
84+
Get a managed window by name.
85+
86+
- **name** `string` - Window name
87+
88+
Returns: `BrowserWindow | undefined`
89+
90+
### `windowManager.getById(id)`
91+
92+
Get a managed window by Electron window id.
93+
94+
- **id** `number` - Window id
95+
96+
Returns: `BrowserWindow | undefined`
97+
98+
### `windowManager.getAll()`
99+
100+
Get all managed windows.
101+
102+
Returns: `Object` - Object with window IDs as keys
103+
104+
### `WindowManager.setGlobalUserAgent(ua)`
105+
106+
Static method. Set global user agent for all windows.
107+
108+
- **ua** `string` - User agent string
109+
110+
## Roadmap
81111

82112
- [ ] support storage of window configuration
83-
- [ ] clone pointed window
113+
- [ ] support window cloning
114+
115+
<!-- GITCONTRIBUTOR_START -->
116+
117+
## Contributors
118+
119+
|[<img src="https://avatars.githubusercontent.com/u/1011681?v=4" width="80px;"/><br/><sub><b>xudafeng</b></sub>](https://github.com/xudafeng)<br/>|[<img src="https://avatars.githubusercontent.com/u/17586742?v=4" width="80px;"/><br/><sub><b>sriting</b></sub>](https://github.com/sriting)<br/>|[<img src="https://avatars.githubusercontent.com/u/30524126?v=4" width="80px;"/><br/><sub><b>z0gSh1u</b></sub>](https://github.com/z0gSh1u)<br/>|[<img src="https://avatars.githubusercontent.com/u/52845048?v=4" width="80px;"/><br/><sub><b>snapre</b></sub>](https://github.com/snapre)<br/>|[<img src="https://avatars.githubusercontent.com/u/12660278?v=4" width="80px;"/><br/><sub><b>ColaDaddyz</b></sub>](https://github.com/ColaDaddyz)<br/>|[<img src="https://avatars.githubusercontent.com/in/1143301?v=4" width="80px;"/><br/><sub><b>Copilot</b></sub>](https://github.com/apps/copilot-swe-agent)<br/>|
120+
| :---: | :---: | :---: | :---: | :---: | :---: |
121+
[<img src="https://avatars.githubusercontent.com/u/11213298?v=4" width="80px;"/><br/><sub><b>WynterDing</b></sub>](https://github.com/WynterDing)<br/>|[<img src="https://avatars.githubusercontent.com/u/4081746?v=4" width="80px;"/><br/><sub><b>zlyi</b></sub>](https://github.com/zlyi)<br/>|[<img src="https://avatars.githubusercontent.com/u/50158871?v=4" width="80px;"/><br/><sub><b>moshangqi</b></sub>](https://github.com/moshangqi)<br/>
122+
123+
This project follows the git-contributor [spec](https://github.com/xudafeng/git-contributor), auto updated at `Mon Feb 23 2026 15:23:51 GMT+0800`.
124+
125+
<!-- GITCONTRIBUTOR_END -->
84126

85127
## License
86128

index.d.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,3 +153,7 @@ declare class WindowsManager {
153153
}
154154

155155
export = WindowsManager
156+
157+
declare namespace WindowsManager {
158+
export type { Window, StatefulWindow }
159+
}

lib/helper.js

Lines changed: 0 additions & 3 deletions
This file was deleted.

package.json

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -30,22 +30,25 @@
3030
"eslint": "7",
3131
"eslint-config-egg": "12",
3232
"eslint-plugin-mocha": "~10.0.0",
33-
"git-contributor": "*",
34-
"husky": "*",
35-
"mocha": "*",
36-
"nyc": "*"
33+
"git-contributor": "2",
34+
"husky": "9",
35+
"mocha": "10",
36+
"nyc": "17"
3737
},
3838
"scripts": {
3939
"dev": "electron ./start.js",
40-
"test": "nyc --reporter=lcov --reporter=text mocha",
40+
"pretest": "rm -rf .nyc_output coverage",
41+
"test": "nyc mocha",
4142
"test:e2e": "npx playwright test",
42-
"lint": "eslint . --fix",
43-
"contributor": "git-contributor"
43+
"lint": "eslint .",
44+
"lint:fix": "eslint . --fix",
45+
"contributor": "git-contributor",
46+
"prepare": "husky"
4447
},
45-
"husky": {
46-
"hooks": {
47-
"pre-commit": "npm run lint"
48-
}
49-
},
50-
"license": "MIT"
48+
"license": "MIT",
49+
"pnpm": {
50+
"onlyBuiltDependencies": [
51+
"electron"
52+
]
53+
}
5154
}

0 commit comments

Comments
 (0)