browser-commander 0.10.0 → 0.12.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,8 @@
1
1
  import { describe, it } from 'node:test';
2
2
  import assert from 'node:assert';
3
3
  import {
4
+ content,
5
+ innerText,
4
6
  textContent,
5
7
  inputValue,
6
8
  getAttribute,
@@ -14,6 +16,106 @@ import {
14
16
  } from '../../helpers/mocks.js';
15
17
 
16
18
  describe('content', () => {
19
+ describe('content', () => {
20
+ for (const [engine, createPage] of [
21
+ ['playwright', createMockPlaywrightPage],
22
+ ['puppeteer', createMockPuppeteerPage],
23
+ ]) {
24
+ it(`should return the full page HTML for ${engine}`, async () => {
25
+ const page = createPage();
26
+ page.content = async () =>
27
+ '<!doctype html><html><body>Hello</body></html>';
28
+
29
+ const html = await content({ page, engine });
30
+
31
+ assert.strictEqual(
32
+ html,
33
+ '<!doctype html><html><body>Hello</body></html>'
34
+ );
35
+ });
36
+ }
37
+
38
+ it('should return null on navigation errors', async () => {
39
+ const page = createMockPlaywrightPage();
40
+ page.content = async () => {
41
+ throw new Error('Execution context was destroyed');
42
+ };
43
+
44
+ assert.strictEqual(await content({ page, engine: 'playwright' }), null);
45
+ });
46
+ });
47
+
48
+ describe('innerText', () => {
49
+ it('should return rendered text for Playwright', async () => {
50
+ const page = createMockPlaywrightPage({
51
+ elements: { main: { innerText: 'Rendered text', count: 1 } },
52
+ });
53
+
54
+ const text = await innerText({
55
+ page,
56
+ engine: 'playwright',
57
+ selector: 'main',
58
+ });
59
+
60
+ assert.strictEqual(text, 'Rendered text');
61
+ });
62
+
63
+ it('should return rendered text for Puppeteer', async () => {
64
+ const page = createMockPuppeteerPage({
65
+ elements: { main: { innerText: 'Rendered text', count: 1 } },
66
+ });
67
+ page.evaluate = async () => 'Rendered text';
68
+
69
+ const text = await innerText({
70
+ page,
71
+ engine: 'puppeteer',
72
+ selector: 'main',
73
+ });
74
+
75
+ assert.strictEqual(text, 'Rendered text');
76
+ });
77
+
78
+ it('should default to the document body', async () => {
79
+ const page = createMockPlaywrightPage({
80
+ elements: { body: { innerText: 'Page text', count: 1 } },
81
+ });
82
+
83
+ assert.strictEqual(
84
+ await innerText({ page, engine: 'playwright' }),
85
+ 'Page text'
86
+ );
87
+ });
88
+
89
+ it('should return null when the element is not found', async () => {
90
+ const page = createMockPuppeteerPage({
91
+ elements: { main: { count: 0 } },
92
+ });
93
+
94
+ assert.strictEqual(
95
+ await innerText({ page, engine: 'puppeteer', selector: 'main' }),
96
+ null
97
+ );
98
+ });
99
+
100
+ it('should return null on navigation errors', async () => {
101
+ const page = createMockPlaywrightPage();
102
+ page.locator = () => ({
103
+ count: async () => 1,
104
+ first() {
105
+ return this;
106
+ },
107
+ innerText: async () => {
108
+ throw new Error('Execution context was destroyed');
109
+ },
110
+ });
111
+
112
+ assert.strictEqual(
113
+ await innerText({ page, engine: 'playwright', selector: 'main' }),
114
+ null
115
+ );
116
+ });
117
+ });
118
+
17
119
  describe('textContent', () => {
18
120
  it('should throw when selector is not provided', async () => {
19
121
  const page = createMockPlaywrightPage();
@@ -0,0 +1,73 @@
1
+ import { mkdtempSync, rmSync, writeFileSync } from 'node:fs';
2
+ import { tmpdir } from 'node:os';
3
+ import { join } from 'node:path';
4
+ import assert from 'node:assert/strict';
5
+ import { describe, it } from 'node:test';
6
+
7
+ import { checkWorkflow } from '../../../../scripts/check-ci-workflows.mjs';
8
+
9
+ function withWorkflow(content, callback) {
10
+ const directory = mkdtempSync(join(tmpdir(), 'browser-commander-ci-'));
11
+ const filePath = join(directory, 'workflow.yml');
12
+ writeFileSync(filePath, content);
13
+
14
+ try {
15
+ return callback(filePath);
16
+ } finally {
17
+ rmSync(directory, { force: true, recursive: true });
18
+ }
19
+ }
20
+
21
+ describe('CI workflow policy', () => {
22
+ it('accepts bounded job-scoped checks', () => {
23
+ const workflow = `name: Test
24
+ on: push
25
+ permissions:
26
+ contents: read
27
+ env:
28
+ GIT_CONFIG_KEY_0: init.defaultBranch
29
+ jobs:
30
+ test:
31
+ runs-on: ubuntu-latest
32
+ timeout-minutes: 5
33
+ concurrency:
34
+ group: \${{ github.workflow }}-\${{ github.ref }}-test
35
+ cancel-in-progress: true
36
+ steps:
37
+ - uses: actions/checkout@v6
38
+ `;
39
+
40
+ withWorkflow(workflow, (filePath) => {
41
+ assert.equal(checkWorkflow(filePath), 0);
42
+ });
43
+ });
44
+
45
+ it('rejects workflow-wide cancellation and unbounded jobs', () => {
46
+ const workflow = `name: Test
47
+ on: push
48
+ concurrency:
49
+ group: test
50
+ cancel-in-progress: true
51
+ jobs:
52
+ test:
53
+ runs-on: ubuntu-latest
54
+ steps:
55
+ - uses: actions/checkout@v6
56
+ - run: npm install
57
+ - run: echo "\${{ github.head_ref }}"
58
+ - uses: codecov/codecov-action@v6
59
+ with:
60
+ file: coverage.xml
61
+ `;
62
+ const originalError = console.error;
63
+ console.error = () => {};
64
+
65
+ try {
66
+ withWorkflow(workflow, (filePath) => {
67
+ assert.equal(checkWorkflow(filePath), 7);
68
+ });
69
+ } finally {
70
+ console.error = originalError;
71
+ }
72
+ });
73
+ });
@@ -127,12 +127,25 @@ describe('test runner helper', () => {
127
127
  reporter: 'spec',
128
128
  targets: ['tests/unit'],
129
129
  });
130
- assert.deepEqual(buildNodeTestArgs(options, ['tests/unit/a.test.js']), [
131
- '--test',
132
- '--experimental-test-coverage',
133
- '--test-reporter',
134
- 'spec',
135
- 'tests/unit/a.test.js',
136
- ]);
130
+ assert.deepEqual(
131
+ buildNodeTestArgs(options, ['tests/unit/a.test.js'], '24.18.0'),
132
+ [
133
+ '--test',
134
+ '--test-isolation=none',
135
+ '--experimental-test-coverage',
136
+ '--test-reporter',
137
+ 'spec',
138
+ 'tests/unit/a.test.js',
139
+ ]
140
+ );
141
+ });
142
+
143
+ it('keeps process isolation on Node versions without isolation controls', () => {
144
+ const options = parseTestRunnerArgs(['tests/unit']);
145
+
146
+ assert.deepEqual(
147
+ buildNodeTestArgs(options, ['tests/unit/a.test.js'], '20.20.2'),
148
+ ['--test', 'tests/unit/a.test.js']
149
+ );
137
150
  });
138
151
  });