Skip to content

Commit c124025

Browse files
authored
Merge pull request #661 from ericblade/dev
fix #660 dependencies issue
2 parents cf96c62 + 27a4834 commit c124025

9 files changed

Lines changed: 256 additions & 78 deletions

File tree

.github/workflows/test-pr.yml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,3 +47,9 @@ jobs:
4747
- name: test package require
4848
run: |
4949
npm run test:require
50+
- name: test node bundle decodeSingle
51+
run: npm run test:node-bundle
52+
env:
53+
NODE_OPTIONS: --openssl-legacy-provider
54+
- name: test browser bundle decodeSingle
55+
run: npm run test:browser-bundle

DEPENDENCIES.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,18 @@ These packages are **only used during build/development** and are **not bundled
145145
- **Purpose**: Native file watching for better performance
146146
- **Usage**: Automatically used by Webpack/build tools on macOS
147147

148+
- **`ndarray-pixels`** (^5.0.1)
149+
- **Platform**: Node.js only
150+
- **Purpose**: Image decoding for `decodeSingle` in Node.js
151+
- **Usage**: Required for Node.js `decodeSingle()` support; install with `npm install ndarray-pixels sharp`
152+
- **Note**: Marked external in Node webpack build; not bundled into `lib/quagga.js`
153+
154+
- **`sharp`** (^0.34.0)
155+
- **Platform**: Node.js only
156+
- **Purpose**: Native image processing (used by `ndarray-pixels` on Node.js)
157+
- **Usage**: Required for Node.js `decodeSingle()` support; transitive dependency of `ndarray-pixels`
158+
- **Note**: Marked external in Node webpack build; not bundled into `lib/quagga.js`
159+
148160
---
149161

150162
## Overrides

configs/webpack.node.config.js

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,20 @@ module.exports = {
1010
'http',
1111
'https',
1212
'url',
13+
'sharp',
14+
'ndarray-pixels',
1315
],
1416
};
17+
module.exports.target = 'node';
18+
module.exports.resolve = {
19+
...module.exports.resolve,
20+
// Prefer Node builds of packages (e.g., ndarray-pixels) instead of browser entries
21+
mainFields: ['main', 'module'],
22+
alias: {
23+
// Force ndarray-pixels to resolve to its Node build; webpack 4 lacks conditionNames support
24+
'ndarray-pixels$': 'ndarray-pixels/dist/ndarray-pixels-node.cjs',
25+
},
26+
};
1527
module.exports.output.libraryTarget = 'commonjs';
1628
module.exports.output.library = undefined;
1729
module.exports.plugins = [

cypress/e2e/browser-bundle.cy.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Test that the browser bundle (dist/quagga.min.js) works correctly with decodeSingle
2+
// This validates that the built bundle can decode images in a browser context
3+
4+
/// <reference types="cypress" />
5+
6+
describe('Browser Bundle - decodeSingle', () => {
7+
before(() => {
8+
// Create a minimal test HTML file
9+
const html = `
10+
<!DOCTYPE html>
11+
<html>
12+
<head>
13+
<meta charset="utf-8">
14+
<title>Bundle Test</title>
15+
</head>
16+
<body>
17+
<script src="/dist/quagga.min.js"></script>
18+
</body>
19+
</html>`;
20+
cy.writeFile('cypress/fixtures/bundle-test.html', html);
21+
});
22+
23+
after(() => {
24+
// Clean up the temporary file even if test passes
25+
cy.task('cleanupBundleFixture');
26+
});
27+
28+
beforeEach(() => {
29+
cy.visit('/cypress/fixtures/bundle-test.html');
30+
});
31+
32+
it('should decode a Code 128 barcode from dist/quagga.min.js', () => {
33+
cy.window().should('have.property', 'Quagga');
34+
35+
cy.window().then((win) => {
36+
return new Cypress.Promise((resolve, reject) => {
37+
// Use a fixture image path relative to the server root
38+
const imagePath = '/test/fixtures/code_128/image-001.jpg';
39+
40+
win.Quagga.decodeSingle({
41+
src: imagePath,
42+
numOfWorkers: 0,
43+
inputStream: {
44+
size: 800
45+
},
46+
decoder: {
47+
readers: ['code_128_reader']
48+
},
49+
}, (result: any) => {
50+
if (result && result.codeResult) {
51+
cy.log('Decoded:', result.codeResult.code);
52+
expect(result.codeResult.code).to.be.a('string');
53+
expect(result.codeResult.code.length).to.be.greaterThan(0);
54+
resolve(result);
55+
} else {
56+
reject(new Error('Failed to decode barcode'));
57+
}
58+
});
59+
});
60+
});
61+
});
62+
});

cypress/plugins/index.js

Lines changed: 50 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,67 @@
1616
* @type {Cypress.PluginConfig}
1717
*/
1818
const webpack = require('@cypress/webpack-preprocessor');
19+
const fs = require('fs');
20+
const path = require('path');
1921

2022
module.exports = (on, config) => {
2123
config.env = config.env || {};
2224
config.env.BUILD_ENV = 'production';
23-
25+
// Resolve path to the temporary bundle test fixture
26+
const bundleFixturePath = path.resolve((config.projectRoot || process.cwd()), 'cypress/fixtures/bundle-test.html');
27+
28+
// Expose cleanup tasks to the Cypress runner
29+
on('task', {
30+
deleteFile(filePath) {
31+
try {
32+
if (fs.existsSync(filePath)) {
33+
fs.unlinkSync(filePath);
34+
}
35+
return true;
36+
} catch (err) {
37+
// ENOENT is fine; any other error bubble up for visibility
38+
if (err && err.code === 'ENOENT') return true;
39+
throw err;
40+
}
41+
},
42+
cleanupBundleFixture() {
43+
try {
44+
if (fs.existsSync(bundleFixturePath)) {
45+
fs.unlinkSync(bundleFixturePath);
46+
}
47+
} catch (_) {
48+
// Ignore errors during cleanup
49+
}
50+
return true;
51+
},
52+
fileExists(filePath) {
53+
return fs.existsSync(filePath);
54+
},
55+
});
56+
57+
// Best-effort cleanup on process exit/interrupt, guarded to avoid duplicate handlers
58+
if (!global.__bundleCleanupHandlersRegistered) {
59+
const safeUnlink = () => {
60+
try {
61+
if (fs.existsSync(bundleFixturePath)) {
62+
fs.unlinkSync(bundleFixturePath);
63+
}
64+
} catch (_) {}
65+
};
66+
process.on('exit', safeUnlink);
67+
process.on('SIGINT', () => { safeUnlink(); process.exit(1); });
68+
process.on('SIGTERM', () => { safeUnlink(); process.exit(1);});
69+
global.__bundleCleanupHandlersRegistered = true;
70+
}
71+
2472
if (process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'development') {
2573
const webpackOptions = {
2674
webpackOptions: require('../../configs/webpack.config'),
2775
watchOptions: {},
2876
};
2977
on('file:preprocessor', webpack(webpackOptions));
3078
}
31-
79+
3280
// on('file:preprocessor', require('@cypress/code-coverage/use-babelrc'));
3381
return config;
3482
};

0 commit comments

Comments
 (0)