Skip to content

Commit e5ecfdf

Browse files
authored
Update to a number input field for the interval (#105)
1 parent 4cc2d5a commit e5ecfdf

File tree

5 files changed

+186
-34
lines changed

5 files changed

+186
-34
lines changed

src/content/popup.html

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,7 @@
88

99
<body>
1010
<label>Interval (s):</label>
11-
<input id="update-interval-slider" type="range" min="1" max="5" value="5"/>
12-
<input id="update-interval-value" type="text" readonly="true"/>
11+
<input id="update-interval-input" type="number" min="1" max="5" value="5"/>
1312

1413
<script src="popup.js"></script>
1514
</body>

src/content/popup.js

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
1-
const updateIntervalSlider = document.getElementById("update-interval-slider");
2-
const updateIntervalValue = document.getElementById("update-interval-value");
1+
const updateIntervalInput = document.getElementById("update-interval-input");
32

4-
function updateInterval(ev) {
3+
updateIntervalInput.addEventListener("change", ev => {
54
browser.runtime.sendMessage({
65
name: "set-update-interval",
76
interval: parseInt(ev.target.value),
87
})
9-
}
10-
11-
updateIntervalSlider.addEventListener("change", updateInterval);
12-
updateIntervalSlider.addEventListener("input", ev => {
13-
updateIntervalValue.value = ev.target.value;
148
});
15-
updateIntervalValue.value = updateIntervalSlider.value;

test/helpers/firefox-extension.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,29 @@ class FirefoxExtensionHelper {
149149
console.log(`Screenshot saved: ${filename}`);
150150
}
151151

152+
/**
153+
* Sets up a MutationObserver on the process table to track updates
154+
* Initializes window.__updateCount and window.__updateTimestamps
155+
*/
156+
async setupTableObserver() {
157+
await this.#driver.executeScript(`
158+
window.__updateCount = 0;
159+
window.__updateTimestamps = [];
160+
const tbody = document.getElementById('tbody-processes');
161+
const observer = new MutationObserver((mutations) => {
162+
if (mutations.length > 0) {
163+
window.__updateCount++;
164+
window.__updateTimestamps.push(Date.now());
165+
}
166+
});
167+
observer.observe(tbody, {
168+
childList: true,
169+
subtree: true,
170+
characterData: true
171+
});
172+
`);
173+
}
174+
152175
/**
153176
* Cleanup - quit driver
154177
*/

test/specs/basic.test.js

Lines changed: 3 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ describe('PerfChaser Extension - Basic Tests', function() {
1515
await helper.quit();
1616
});
1717

18-
describe('Extension Installation', function() {
18+
describe('Basic sidebar features', function() {
1919
it('should load the sidebar page', async function() {
2020
await driver.get(helper.sidebarUrl);
2121

@@ -46,37 +46,17 @@ describe('PerfChaser Extension - Basic Tests', function() {
4646

4747
assert.ok(isDisplayed, 'CPU history chart should be displayed');
4848
});
49-
50-
it('should load the popup page', async function() {
51-
await driver.get(helper.popupUrl);
52-
53-
// Verify page loaded by checking body element exists
54-
const body = await driver.findElement(By.css('body'));
55-
assert.ok(body, 'Popup body element should exist');
56-
});
57-
58-
it('should display the update interval controls', async function() {
59-
await driver.get(helper.popupUrl);
60-
61-
// Check for interval slider
62-
const slider = await driver.findElement(By.css('#update-interval-slider'));
63-
assert.ok(slider, 'Update interval slider should exist');
64-
65-
// Check for interval value display
66-
const value = await driver.findElement(By.css('#update-interval-value'));
67-
assert.ok(value, 'Update interval value display should exist');
68-
});
6949
});
7050

7151
describe('Process Data Collection', function() {
7252
it('should collect and display process data', async function() {
7353
await driver.get(helper.sidebarUrl);
7454

75-
// Wait up to 15 seconds for process data to load
55+
// Wait up to 5 seconds for process data to load
7656
await driver.wait(async () => {
7757
const rows = await driver.findElements(By.css('#tbody-processes tr'));
7858
return rows.length > 0;
79-
}, 15000, 'Expected process data to be loaded');
59+
}, 5000, 'Expected process data to be loaded');
8060

8161
const rows = await driver.findElements(By.css('#tbody-processes tr'));
8262
assert.ok(rows.length > 0, 'Should have at least one process row');

test/specs/popup-interval.test.js

Lines changed: 157 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,157 @@
1+
import assert from 'assert';
2+
import { By, until, Key } from 'selenium-webdriver';
3+
import FirefoxExtensionHelper from '../helpers/firefox-extension.js';
4+
5+
describe('PerfChaser Extension - Popup Interval Tests', function() {
6+
let helper;
7+
let driver;
8+
9+
before(async function() {
10+
helper = new FirefoxExtensionHelper();
11+
driver = await helper.init();
12+
});
13+
14+
after(async function() {
15+
await helper.quit();
16+
});
17+
18+
describe('Update Interval Controls', function() {
19+
it('should display the update interval number input with correct attributes', async function() {
20+
await driver.get(helper.popupUrl);
21+
22+
const input = await driver.findElement(By.css('#update-interval-input'));
23+
assert.ok(input, 'Update interval input should exist');
24+
25+
const inputType = await input.getAttribute('type');
26+
assert.strictEqual(inputType, 'number', 'Input should be type number');
27+
28+
const value = await input.getAttribute('value');
29+
assert.strictEqual(value, '5', 'Default interval should be 5 seconds');
30+
31+
const min = await input.getAttribute('min');
32+
const max = await input.getAttribute('max');
33+
assert.strictEqual(min, '1', 'Min interval should be 1 second');
34+
assert.strictEqual(max, '5', 'Max interval should be 5 seconds');
35+
});
36+
37+
it('should allow changing the interval value', async function() {
38+
await driver.get(helper.popupUrl);
39+
40+
const input = await driver.findElement(By.css('#update-interval-input'));
41+
42+
// Clear and set new value
43+
await input.clear();
44+
await input.sendKeys('2', Key.RETURN);
45+
46+
const newValue = await input.getAttribute('value');
47+
assert.strictEqual(newValue, '2', 'Interval value should be updated to 2');
48+
});
49+
});
50+
51+
describe('Interval Application to Background Script', function() {
52+
it('should apply interval changes to sidebar updates', async function() {
53+
// This test verifies that changing the interval in the popup
54+
// correctly updates the background script's alarm timer
55+
56+
// Step 1: Set a short interval (1 second) via the popup
57+
await driver.get(helper.popupUrl);
58+
const input = await driver.findElement(By.css('#update-interval-input'));
59+
await input.clear();
60+
await input.sendKeys('1', Key.RETURN);
61+
62+
// Step 2: Open sidebar and wait for initial data
63+
await driver.get(helper.sidebarUrl);
64+
await driver.wait(async () => {
65+
const rows = await driver.findElements(By.css('#tbody-processes tr'));
66+
return rows.length > 0;
67+
}, 10000, 'Expected initial process data to be loaded');
68+
69+
// Step 3: Set up a MutationObserver to detect table updates
70+
await helper.setupTableObserver();
71+
72+
const startTime = Date.now();
73+
74+
// Step 4: Wait for a table update to occur
75+
await driver.wait(async () => {
76+
const updateCount = await driver.executeScript('return window.__updateCount');
77+
return updateCount > 0;
78+
}, 3000, 'Process table should update within 3 seconds with 1s interval');
79+
80+
const timeElapsed = Date.now() - startTime;
81+
82+
// The update should happen within ~1-2 seconds (allowing some margin)
83+
assert.ok(timeElapsed < 2500,
84+
`Update should occur within ~2 seconds with 1s interval (took ${timeElapsed}ms)`);
85+
});
86+
87+
it('should respect longer intervals', async function() {
88+
// Set interval to 5 seconds
89+
await driver.get(helper.popupUrl);
90+
const input = await driver.findElement(By.css('#update-interval-input'));
91+
await input.clear();
92+
await input.sendKeys('5', Key.RETURN);
93+
94+
// Go to sidebar
95+
await driver.get(helper.sidebarUrl);
96+
await driver.wait(async () => {
97+
const rows = await driver.findElements(By.css('#tbody-processes tr'));
98+
return rows.length > 0;
99+
}, 10000, 'Sidebar should load data');
100+
101+
// Set up MutationObserver to count table updates
102+
await helper.setupTableObserver();
103+
104+
// Wait for 7 seconds
105+
await driver.sleep(7000);
106+
107+
// Check update count - should be at most 2 updates in 7 seconds with 5s interval
108+
// (one might happen right away, then one at ~5s, possibly one at ~10s but we stop at 7s)
109+
const updateCount = await driver.executeScript('return window.__updateCount');
110+
111+
assert.ok(updateCount <= 2,
112+
`With 5s interval, should have at most 2 updates in 7 seconds (got ${updateCount})`);
113+
});
114+
115+
it('should immediately apply interval changes', async function() {
116+
// This test verifies that changing the interval immediately recreates the alarm
117+
// rather than waiting for the next scheduled update
118+
119+
// Start with 5 second interval
120+
await driver.get(helper.popupUrl);
121+
let input = await driver.findElement(By.css('#update-interval-input'));
122+
await input.clear();
123+
await input.sendKeys('5', Key.RETURN);
124+
125+
// Wait a moment for the change to apply
126+
await driver.sleep(500);
127+
128+
// Change to 1 second interval
129+
await driver.get(helper.popupUrl);
130+
input = await driver.findElement(By.css('#update-interval-input'));
131+
await input.clear();
132+
await input.sendKeys('1', Key.RETURN);
133+
134+
// Go to sidebar and set up MutationObserver
135+
await driver.get(helper.sidebarUrl);
136+
await driver.wait(async () => {
137+
const rows = await driver.findElements(By.css('#tbody-processes tr'));
138+
return rows.length > 0;
139+
}, 10000, 'Sidebar should load');
140+
141+
await helper.setupTableObserver();
142+
143+
// Should receive an update within ~2 seconds, not have to wait 5 seconds
144+
const startTime = Date.now();
145+
await driver.wait(async () => {
146+
const updateCount = await driver.executeScript('return window.__updateCount');
147+
return updateCount > 0;
148+
}, 3000, 'Should receive update quickly after interval change');
149+
150+
const timeElapsed = Date.now() - startTime;
151+
152+
// Should not have to wait the old 5 second interval
153+
assert.ok(timeElapsed < 3000,
154+
`Update should occur within ~2s after changing to 1s interval (took ${timeElapsed}ms)`);
155+
});
156+
});
157+
});

0 commit comments

Comments
 (0)