Added scanning barcodes with a camera
This commit is contained in:
62
quagga2/quagga2-1.12.1/cypress/e2e/browser-bundle.cy.ts
Normal file
62
quagga2/quagga2-1.12.1/cypress/e2e/browser-bundle.cy.ts
Normal file
@@ -0,0 +1,62 @@
|
||||
// Test that the browser bundle (dist/quagga.min.js) works correctly with decodeSingle
|
||||
// This validates that the built bundle can decode images in a browser context
|
||||
|
||||
/// <reference types="cypress" />
|
||||
|
||||
describe('Browser Bundle - decodeSingle', () => {
|
||||
before(() => {
|
||||
// Create a minimal test HTML file
|
||||
const html = `
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Bundle Test</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="/dist/quagga.min.js"></script>
|
||||
</body>
|
||||
</html>`;
|
||||
cy.writeFile('cypress/fixtures/bundle-test.html', html);
|
||||
});
|
||||
|
||||
after(() => {
|
||||
// Clean up the temporary file even if test passes
|
||||
cy.task('cleanupBundleFixture');
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
cy.visit('/cypress/fixtures/bundle-test.html');
|
||||
});
|
||||
|
||||
it('should decode a Code 128 barcode from dist/quagga.min.js', () => {
|
||||
cy.window().should('have.property', 'Quagga');
|
||||
|
||||
cy.window().then((win) => {
|
||||
return new Cypress.Promise((resolve, reject) => {
|
||||
// Use a fixture image path relative to the server root
|
||||
const imagePath = '/test/fixtures/code_128/image-001.jpg';
|
||||
|
||||
win.Quagga.decodeSingle({
|
||||
src: imagePath,
|
||||
numOfWorkers: 0,
|
||||
inputStream: {
|
||||
size: 800
|
||||
},
|
||||
decoder: {
|
||||
readers: ['code_128_reader']
|
||||
},
|
||||
}, (result: any) => {
|
||||
if (result && result.codeResult) {
|
||||
cy.log('Decoded:', result.codeResult.code);
|
||||
expect(result.codeResult.code).to.be.a('string');
|
||||
expect(result.codeResult.code.length).to.be.greaterThan(0);
|
||||
resolve(result);
|
||||
} else {
|
||||
reject(new Error('Failed to decode barcode'));
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
11
quagga2/quagga2-1.12.1/cypress/e2e/browser.cy.ts
Normal file
11
quagga2/quagga2-1.12.1/cypress/e2e/browser.cy.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
window.ENV = { development: true, production: false, node: false };
|
||||
|
||||
import '../../src/analytics/test/browser/result_collector.spec.ts';
|
||||
import '../../src/input/test/browser/camera_access.spec.ts';
|
||||
import '../../src/input/test/browser/exif_helper.spec';
|
||||
import '../../src/input/test/browser/image_loader.spec.ts';
|
||||
import '../../src/input/test/browser/data_uri.spec.ts';
|
||||
import '../../src/common/test/browser/mediaDevices.spec.ts';
|
||||
import '../../src/input/test/browser/frame_grabber_halfsample.spec.ts';
|
||||
import '../../src/quagga/test/browser/pause_start.spec.ts';
|
||||
import '../../src/quagga/test/browser/initCanvas.spec.ts';
|
||||
156
quagga2/quagga2-1.12.1/cypress/e2e/examples.cy.ts
Normal file
156
quagga2/quagga2-1.12.1/cypress/e2e/examples.cy.ts
Normal file
@@ -0,0 +1,156 @@
|
||||
// E2E tests for example pages
|
||||
describe('Example Pages E2E', () => {
|
||||
describe('live_w_locator.html', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('http://localhost:8080/live_w_locator.html');
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
cy.window().then((win: any) => {
|
||||
if (win.Quagga && win.Quagga.stop) {
|
||||
const stopPromise = win.Quagga.stop();
|
||||
if (stopPromise && typeof stopPromise.then === 'function') {
|
||||
return cy.wrap(stopPromise);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
after(() => {
|
||||
cy.window().then((win: any) => {
|
||||
if (win.Quagga && win.Quagga.stop) {
|
||||
const stopPromise = win.Quagga.stop();
|
||||
if (stopPromise && typeof stopPromise.then === 'function') {
|
||||
return cy.wrap(stopPromise);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
it('should load the page successfully', () => {
|
||||
cy.contains('h1', 'QuaggaJS').should('be.visible');
|
||||
});
|
||||
|
||||
it('should have a camera dropdown', () => {
|
||||
cy.get('select#deviceSelection').should('exist');
|
||||
});
|
||||
|
||||
it('should have a locate checkbox', () => {
|
||||
cy.get('input[name="locate"]').should('exist');
|
||||
});
|
||||
|
||||
it('should have canvas elements', () => {
|
||||
// Canvas is created by Quagga inside #interactive div
|
||||
cy.get('#interactive').should('exist');
|
||||
});
|
||||
|
||||
it('should have Quagga available on window', () => {
|
||||
cy.window().its('Quagga').should('exist');
|
||||
});
|
||||
|
||||
it('should toggle locate checkbox', () => {
|
||||
cy.get('input[name="locate"]').uncheck().should('not.be.checked');
|
||||
cy.get('input[name="locate"]').check().should('be.checked');
|
||||
});
|
||||
|
||||
it('should populate camera dropdown with devices', () => {
|
||||
// Wait for devices to be enumerated and dropdown populated
|
||||
cy.get('select#deviceSelection option', { timeout: 10000 })
|
||||
.should('have.length.at.least', 1);
|
||||
});
|
||||
|
||||
|
||||
it('provides scanning area box when locate=false', () => {
|
||||
// Wait for Quagga to be initialized and processing frames before toggling locate
|
||||
cy.window().then((win: any) => {
|
||||
expect(win.Quagga).to.exist;
|
||||
return new Cypress.Promise((resolve) => {
|
||||
const timeout = setTimeout(() => resolve(null), 1500);
|
||||
win.Quagga.onProcessed(() => {
|
||||
clearTimeout(timeout);
|
||||
resolve(null);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Now toggle locate off and wait for reinit
|
||||
cy.get('input[name="locate"]').uncheck().should('not.be.checked').trigger('change');
|
||||
cy.wait(400); // Allow time for debounced reinit (250ms) + init completion
|
||||
|
||||
cy.window().then((win: any) => {
|
||||
expect(win.Quagga).to.exist;
|
||||
expect(win.Quagga.onProcessed).to.be.a('function');
|
||||
|
||||
const p = new Cypress.Promise((resolve) => {
|
||||
const timeout = setTimeout(() => resolve(null), 2000);
|
||||
|
||||
win.Quagga.onProcessed(function (result: any) {
|
||||
if (result && (result.box || (result.boxes && result.boxes.length > 0))) {
|
||||
clearTimeout(timeout);
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
});
|
||||
return cy.wrap(p, { timeout: 3000 });
|
||||
}).then((result: any) => {
|
||||
expect(result, 'Should receive result with box or boxes').to.exist;
|
||||
// When locate=false, should have either result.box or result.boxes
|
||||
const hasBox = result.box && Array.isArray(result.box) && result.box.length === 4;
|
||||
const hasBoxes = result.boxes && Array.isArray(result.boxes) && result.boxes.length > 0;
|
||||
expect(hasBox || hasBoxes, 'Should have either result.box or result.boxes with scanning area').to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it('continues processing frames after resolution change', () => {
|
||||
// Select a different resolution option dynamically (choose last option if available)
|
||||
cy.contains('label', 'Resolution (width)')
|
||||
.find('select[name="input-stream_constraints"]').then($sel => {
|
||||
const current = ($sel[0] as HTMLSelectElement).value;
|
||||
const options = Array.from(($sel[0] as HTMLSelectElement).options).map(o => o.value);
|
||||
const alt = options.reverse().find(v => v !== current) || current;
|
||||
cy.wrap($sel).select(alt);
|
||||
});
|
||||
// Verify frames continue after resolution change
|
||||
cy.window().then((win: any) => {
|
||||
expect(win.Quagga).to.exist;
|
||||
expect(win.Quagga.onProcessed).to.be.a('function');
|
||||
let count = 0;
|
||||
const p = new Cypress.Promise((resolve) => {
|
||||
const timeout = setTimeout(() => resolve(null), 3000);
|
||||
win.Quagga.onProcessed(() => {
|
||||
count++;
|
||||
if (count >= 3) {
|
||||
clearTimeout(timeout);
|
||||
resolve(null);
|
||||
}
|
||||
});
|
||||
});
|
||||
return cy.wrap(p, { timeout: 3500 }).then(() => {
|
||||
expect(count).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('continues processing frames after patch size change', () => {
|
||||
cy.contains('label', 'Patch-Size')
|
||||
.find('select[name="locator_patch-size"]').select('large');
|
||||
cy.window().then((win: any) => {
|
||||
expect(win.Quagga).to.exist;
|
||||
expect(win.Quagga.onProcessed).to.be.a('function');
|
||||
let count = 0;
|
||||
const p = new Cypress.Promise((resolve) => {
|
||||
win.Quagga.onProcessed(() => { count++; if (count >= 3) resolve(null); });
|
||||
});
|
||||
return cy.wrap(p, { timeout: 3000 }).then(() => {
|
||||
expect(count).to.be.greaterThan(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('hides zoom and torch controls when unsupported', () => {
|
||||
// Labels wrap the inputs and are set to display:none when capability missing
|
||||
cy.get('label:has(select[name="settings_zoom"])').should('have.css', 'display', 'none');
|
||||
cy.get('label:has(input[name="settings_torch"])').should('have.css', 'display', 'none');
|
||||
});
|
||||
});
|
||||
});
|
||||
22
quagga2/quagga2-1.12.1/cypress/e2e/integration.cy.ts
Normal file
22
quagga2/quagga2-1.12.1/cypress/e2e/integration.cy.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
window.ENV = { development: true, production: false, node: false };
|
||||
|
||||
// Integration tests that aren't specific decoders
|
||||
import '../../test/integration/external-reader.spec.ts';
|
||||
import '../../test/integration/integration.spec.ts';
|
||||
import '../../test/integration/reader-order.spec.ts';
|
||||
|
||||
// Decoders
|
||||
import '../../test/integration/decoders/2of5.spec.ts';
|
||||
import '../../test/integration/decoders/codabar.spec.ts';
|
||||
import '../../test/integration/decoders/code_128.spec.ts';
|
||||
import '../../test/integration/decoders/code_32.spec.ts';
|
||||
import '../../test/integration/decoders/code_39_vin.spec.ts';
|
||||
import '../../test/integration/decoders/code_39.spec.ts';
|
||||
import '../../test/integration/decoders/code_93.spec.ts';
|
||||
import '../../test/integration/decoders/ean_8.spec.ts';
|
||||
import '../../test/integration/decoders/ean_extended.spec.ts';
|
||||
import '../../test/integration/decoders/ean_supplement_format.spec.ts';
|
||||
import '../../test/integration/decoders/ean.spec.ts';
|
||||
import '../../test/integration/decoders/i2of5.spec.ts';
|
||||
import '../../test/integration/decoders/upc_e.spec.ts';
|
||||
import '../../test/integration/decoders/upc.spec.ts';
|
||||
@@ -0,0 +1 @@
|
||||
import '../../../../test/integration/decoders/pharmacode.spec.ts';
|
||||
18
quagga2/quagga2-1.12.1/cypress/e2e/universal.cy.ts
Normal file
18
quagga2/quagga2-1.12.1/cypress/e2e/universal.cy.ts
Normal file
@@ -0,0 +1,18 @@
|
||||
window.ENV = { development: true, production: false, node: false };
|
||||
|
||||
import '../../src/common/test/array_helper.spec.ts';
|
||||
import '../../src/common/test/area_overlay.spec.ts';
|
||||
import '../../src/common/test/cv_utils.spec';
|
||||
import '../../src/common/test/events.spec.ts';
|
||||
import '../../src/locator/test/barcode_locator.spec.ts';
|
||||
import '../../src/locator/test/skeletonizer.spec.ts';
|
||||
import '../../src/quagga/test/transform.spec.ts';
|
||||
// Tests for Exception class (toJSON serialization)
|
||||
import '../../src/quagga/test/Exception.spec.ts';
|
||||
// Tests for Quagga class (transformResult method)
|
||||
import '../../src/quagga/test/quagga.spec.ts';
|
||||
// Tests for drawScannerArea method
|
||||
import '../../src/quagga/test/drawScannerArea.spec.ts';
|
||||
import '../../src/common/test/image_wrapper.spec.ts';
|
||||
// Tests for QuaggaJSStaticInterface (init method)
|
||||
import '../../src/test/quagga.spec.ts';
|
||||
82
quagga2/quagga2-1.12.1/cypress/plugins/index.js
Normal file
82
quagga2/quagga2-1.12.1/cypress/plugins/index.js
Normal file
@@ -0,0 +1,82 @@
|
||||
/// <reference types="cypress" />
|
||||
// ***********************************************************
|
||||
// This example plugins/index.js can be used to load plugins
|
||||
//
|
||||
// You can change the location of this file or turn off loading
|
||||
// the plugins file with the 'pluginsFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/plugins-guide
|
||||
// ***********************************************************
|
||||
|
||||
// This function is called when a project is opened or re-opened (e.g. due to
|
||||
// the project's config changing)
|
||||
|
||||
/**
|
||||
* @type {Cypress.PluginConfig}
|
||||
*/
|
||||
const webpack = require('@cypress/webpack-preprocessor');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
module.exports = (on, config) => {
|
||||
config.env = config.env || {};
|
||||
config.env.BUILD_ENV = 'production';
|
||||
// Resolve path to the temporary bundle test fixture
|
||||
const bundleFixturePath = path.resolve((config.projectRoot || process.cwd()), 'cypress/fixtures/bundle-test.html');
|
||||
|
||||
// Expose cleanup tasks to the Cypress runner
|
||||
on('task', {
|
||||
deleteFile(filePath) {
|
||||
try {
|
||||
if (fs.existsSync(filePath)) {
|
||||
fs.unlinkSync(filePath);
|
||||
}
|
||||
return true;
|
||||
} catch (err) {
|
||||
// ENOENT is fine; any other error bubble up for visibility
|
||||
if (err && err.code === 'ENOENT') return true;
|
||||
throw err;
|
||||
}
|
||||
},
|
||||
cleanupBundleFixture() {
|
||||
try {
|
||||
if (fs.existsSync(bundleFixturePath)) {
|
||||
fs.unlinkSync(bundleFixturePath);
|
||||
}
|
||||
} catch (_) {
|
||||
// Ignore errors during cleanup
|
||||
}
|
||||
return true;
|
||||
},
|
||||
fileExists(filePath) {
|
||||
return fs.existsSync(filePath);
|
||||
},
|
||||
});
|
||||
|
||||
// Best-effort cleanup on process exit/interrupt, guarded to avoid duplicate handlers
|
||||
if (!global.__bundleCleanupHandlersRegistered) {
|
||||
const safeUnlink = () => {
|
||||
try {
|
||||
if (fs.existsSync(bundleFixturePath)) {
|
||||
fs.unlinkSync(bundleFixturePath);
|
||||
}
|
||||
} catch (_) {}
|
||||
};
|
||||
process.on('exit', safeUnlink);
|
||||
process.on('SIGINT', () => { safeUnlink(); process.exit(1); });
|
||||
process.on('SIGTERM', () => { safeUnlink(); process.exit(1);});
|
||||
global.__bundleCleanupHandlersRegistered = true;
|
||||
}
|
||||
|
||||
if (process.env.NODE_ENV === 'test' || process.env.NODE_ENV === 'development') {
|
||||
const webpackOptions = {
|
||||
webpackOptions: require('../../configs/webpack.config'),
|
||||
watchOptions: {},
|
||||
};
|
||||
on('file:preprocessor', webpack(webpackOptions));
|
||||
}
|
||||
|
||||
// on('file:preprocessor', require('@cypress/code-coverage/use-babelrc'));
|
||||
return config;
|
||||
};
|
||||
25
quagga2/quagga2-1.12.1/cypress/support/commands.js
Normal file
25
quagga2/quagga2-1.12.1/cypress/support/commands.js
Normal file
@@ -0,0 +1,25 @@
|
||||
// ***********************************************
|
||||
// This example commands.js shows you how to
|
||||
// create various custom commands and overwrite
|
||||
// existing commands.
|
||||
//
|
||||
// For more comprehensive examples of custom
|
||||
// commands please read more here:
|
||||
// https://on.cypress.io/custom-commands
|
||||
// ***********************************************
|
||||
//
|
||||
//
|
||||
// -- This is a parent command --
|
||||
// Cypress.Commands.add("login", (email, password) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a child command --
|
||||
// Cypress.Commands.add("drag", { prevSubject: 'element'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This is a dual command --
|
||||
// Cypress.Commands.add("dismiss", { prevSubject: 'optional'}, (subject, options) => { ... })
|
||||
//
|
||||
//
|
||||
// -- This will overwrite an existing command --
|
||||
// Cypress.Commands.overwrite("visit", (originalFn, url, options) => { ... })
|
||||
21
quagga2/quagga2-1.12.1/cypress/support/e2e.js
Normal file
21
quagga2/quagga2-1.12.1/cypress/support/e2e.js
Normal file
@@ -0,0 +1,21 @@
|
||||
// ***********************************************************
|
||||
// This example support/index.js is processed and
|
||||
// loaded automatically before your test files.
|
||||
//
|
||||
// This is a great place to put global configuration and
|
||||
// behavior that modifies Cypress.
|
||||
//
|
||||
// You can change the location of this file or turn off
|
||||
// automatically serving support files with the
|
||||
// 'supportFile' configuration option.
|
||||
//
|
||||
// You can read more here:
|
||||
// https://on.cypress.io/configuration
|
||||
// ***********************************************************
|
||||
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
import '@cypress/code-coverage/support';
|
||||
|
||||
// Alternatively you can use CommonJS syntax:
|
||||
// require('./commands')
|
||||
6
quagga2/quagga2-1.12.1/cypress/tsconfig.json
Normal file
6
quagga2/quagga2-1.12.1/cypress/tsconfig.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"types": ["cypress"]
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user