Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: improve worker tests #1757

Merged
merged 5 commits into from
Dec 5, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
14 changes: 10 additions & 4 deletions src/lib/PingTimer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ export default class PingTimer {

private checkPing: () => void

private setTimeout = isBrowser ? setT : setTimeout
// dont directly assign globals to class props otherwise this throws in web workers: Uncaught TypeError: Illegal invocation
// See: https://stackoverflow.com/questions/9677985/uncaught-typeerror-illegal-invocation-in-chrome
private _setTimeout: typeof setT =
isBrowser && !isWebWorker
? setT
: (func, time) => setTimeout(func, time)

private clearTimeout = isBrowser ? clearT : clearTimeout
private _clearTimeout: typeof clearT =
isBrowser && !isWebWorker ? clearT : (timer) => clearTimeout(timer)

constructor(keepalive: number, checkPing: () => void) {
this.keepalive = keepalive * 1000
Expand All @@ -19,15 +25,15 @@ export default class PingTimer {
}

private setup() {
this.timer = this.setTimeout(() => {
this.timer = this._setTimeout(() => {
this.checkPing()
this.reschedule()
}, this.keepalive)
}

clear() {
if (this.timer) {
this.clearTimeout(this.timer)
this._clearTimeout(this.timer)
this.timer = null
}
}
Expand Down
94 changes: 52 additions & 42 deletions test/browser/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,14 @@ import { expect } from '@esm-bundle/chai';
import mqtt from '../../'; // this will resolve to mqtt/dist/mqtt.esm.js

// needed to test no-esm version /dist/mqtt.js
/** @type { import('../../src').MqttClient }*/
/** @type { import('../../src') }*/
const mqtt2 = window.mqtt

// get browser name
const userAgent = navigator.userAgent.toLowerCase().replace(/ /g, '_').replace(/\//g, '_')

let browser = 'unknown'

console.log('userAgent:', userAgent)

if (userAgent.includes('chrome')) {
browser = 'chrome'
} else if (userAgent.includes('firefox')) {
Expand All @@ -21,40 +19,50 @@ if (userAgent.includes('chrome')) {
}

const browserTopic = `test/${browser}`
console.log('User Agent:', userAgent)
console.log('Browser:', browser)

console.log('browser:', browser)

function run(proto, port, cb) {

function testProto(proto, port, cb = () => { }) {
const testTopic = `${browserTopic}/${proto}`

describe('MQTT.js browser test with ' + proto.toUpperCase(), () => {
after(() => {
if (cb) {
if (client) {
client.end(() => {
cb()
client = null;
});
} else {
cb()
}
})

const client = mqtt.connect(`${proto}://localhost:${port}`, {
// log: console.log.bind(console),
})
client.on('offline', () => {
console.log('client offline')
})
client.on('connect', () => {
console.log('client connect')
})
client.on('reconnect', () => {
console.log('client reconnect')
})
/** @type { import('../../src').MqttClient }*/
let client = null;

it('should connect-publish-subscribe', (done) => {
client = mqtt.connect(`${proto}://localhost:${port}`, {
// log: console.log.bind(console),
clientId: `testClient-${browser}-${proto}`,
})
client.on('offline', () => {
console.log('client offline')
done(new Error('client offline'))
})
client.on('connect', () => {
console.log('client connect')
})
client.on('reconnect', () => {
console.log('client reconnect')
})

const payload = 'Hello World!'
client.on('connect', () => {
client.on('message', (topic, msg) => {
expect(topic).to.equal(testTopic);
expect(msg.toString()).to.equal(payload);
client.end(() => {
client = null;
done();
});
});
Expand All @@ -76,30 +84,32 @@ function run(proto, port, cb) {
})
}

it('should work with non-ESM version', () => {
expect(mqtt2).to.exist
expect(mqtt2.connect).to.exist
expect(mqtt2.connect).to.be.a('function')
})
describe('MQTT.js browser tests', () => {
it('should work with ESM version', (done) => {
expect(mqtt2).to.exist
expect(mqtt2.connect).to.be.a('function')
expect(mqtt2.Client).to.be.a('function')
done()
})

it('should work in a Web Worker', (done) => {
const worker = new Worker('test/browser/worker.js')
worker.onmessage = (e) => {
if (e.data === 'worker ready') {
done()
} else {
done(Error(e.data))
}
}

run('ws', window.wsPort, () => {
run('wss', window.wssPort, () => {
describe('MQTT.js browser test with web worker', () => {
it('should work with web worker', async () => {
const worker = new Worker('test/browser/worker.js')
const ready = new Promise((resolve, reject) => {
worker.onmessage = (e) => {
if (e.data === 'worker ready') {
resolve()
} else {
reject(e.data)
}
}
})
await ready
})
})
worker.onerror = (e) => {
done(Error(e.message))
}
})

testProto('ws', window.wsPort, () => {
testProto('wss', window.wssPort)
})
})


26 changes: 23 additions & 3 deletions test/browser/worker.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
// test mqttjs in worker

importScripts('/dist/mqtt.js');

/** @type { import('../../src').MqttClient }*/
const MQTT = mqtt;

postMessage(typeof MQTT?.connect === 'function' ? 'worker ready' : 'worker error');
const client = MQTT.connect(`ws://localhost:4000`, {
clientId: `testClient-worker_` + Math.random().toString(16).substr(2, 8),
});

client.on('offline', () => {
console.log('worker client offline');
})

client.on('reconnect', () => {
console.log('worker client reconnect');
})

client.on('error', (err) => {
console.log('worker client error', err);
})

client.on('connect', () => {
console.log('worker client connect');
client.end(() => {
console.log('worker client end');
postMessage('worker ready');
});
})
2 changes: 2 additions & 0 deletions web-test-runner.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ await start({
wssPort,
key: './test/certs/server-key.pem',
cert: './test/certs/server-cert.pem',
verbose: true,
stats: false
})

console.log('Broker setup done')
Expand Down