{"id":13567807,"url":"https://github.com/httptoolkit/mockrtc","last_synced_at":"2025-05-15T23:07:53.577Z","repository":{"id":38002390,"uuid":"427474395","full_name":"httptoolkit/mockrtc","owner":"httptoolkit","description":"Powerful friendly WebRTC mock peer \u0026 proxy","archived":false,"fork":false,"pushed_at":"2025-01-13T13:39:25.000Z","size":412,"stargazers_count":290,"open_issues_count":3,"forks_count":9,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-05-10T01:06:09.860Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/httptoolkit.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-11-12T19:29:23.000Z","updated_at":"2025-02-20T08:30:27.000Z","dependencies_parsed_at":"2023-12-11T22:59:57.804Z","dependency_job_id":"70145dda-8efb-4062-80a1-7048976a8714","html_url":"https://github.com/httptoolkit/mockrtc","commit_stats":{"total_commits":139,"total_committers":2,"mean_commits":69.5,"dds":0.007194244604316502,"last_synced_commit":"f11793608b4cd9fb4e6597c6032607a5ad3d3ca5"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httptoolkit%2Fmockrtc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httptoolkit%2Fmockrtc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httptoolkit%2Fmockrtc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/httptoolkit%2Fmockrtc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/httptoolkit","download_url":"https://codeload.github.com/httptoolkit/mockrtc/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254436949,"owners_count":22070947,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-08-01T13:02:44.184Z","updated_at":"2025-05-15T23:07:47.681Z","avatar_url":"https://github.com/httptoolkit.png","language":"TypeScript","readme":"# MockRTC [![Build Status](https://github.com/httptoolkit/mockrtc/actions/workflows/ci.yml/badge.svg)](https://github.com/httptoolkit/mockrtc/actions) [![Available on NPM](https://img.shields.io/npm/v/mockrtc.svg?)](https://npmjs.com/package/mockrtc)\n\n\u003e _Part of [HTTP Toolkit](https://httptoolkit.tech): powerful tools for building, testing \u0026 debugging HTTP(S), WebSockets and WebRTC_\n\nMockRTC lets you intercept, assert on and mock WebRTC peers. This makes it possible to:\n\n* Build automated tests for WebRTC traffic.\n* Simulate WebRTC errors in a reliable reproducible way.\n* Capture and inspect traffic between real WebRTC peers for debugging.\n* Create WebRTC proxy peers to automate message transformation, monitoring or logging.\n\n---\n\n:warning: _MockRTC is still new \u0026 rapidly developing!_ :warning:\n\n_Everything described here works today, but there's lots more to come, and some advanced WebRTC use cases may run into rough edges. If you hit any problems or missing features, please [open an issue](https://github.com/httptoolkit/mockrtc/issues/new)._\n\n---\n\n## Example\n\nLet's write an automated test with MockRTC. To test WebRTC-based code, you will typically need to:\n\n* Start a MockRTC mock session\n* Define rules that match and mock the traffic you're interested in\n* Create a WebRTC connection to a mock peer, by either:\n    * Using MockRTC's offer or answer directly.\n    * Applying the provided `MockRTC.hookWebRTCConnection` hook function to your RTC connection, and then connecting to any other real peer as normal.\n    * Call the provided `MockRTC.hookAllWebRTC` global hook function before creating your connection(s), to hook all WebRTC connections automatically.\n\nA simple example of that, running as a test in a browser with the built-in WebRTC APIs, and using a mock answer explicitly, looks like this:\n\n```typescript\nimport * as MockRTC from 'mockrtc'\nconst mockRTC = MockRTC.getRemote({ recordMessages: true });\n\ndescribe(\"MockRTC\", () =\u003e {\n\n    // Start \u0026 stop MockRTC between tests\n    beforeEach(() =\u003e mockRTC.start());\n    afterEach(() =\u003e mockRTC.stop());\n\n    it(\"lets you mock behaviour and assert on RTC interactions\", async () =\u003e {\n        // Create a mock peer who sends 'Goodbye' after receiving its first message.\n        const mockPeer = await mockRTC\n          .buildPeer()\n          .waitForNextMessage()\n          .thenSend('Goodbye');\n\n        // Create a real WebRTC connection and data channel:\n        const localConnection = new RTCPeerConnection();\n        const dataChannel = localConnection.createDataChannel(\"dataChannel\");\n\n        const localOffer = await localConnection.createOffer();\n        await localConnection.setLocalDescription(localOffer);\n\n        // Get a mock answer to connect to our mock peer:\n        const { answer } = await mockPeer.answerOffer(localOffer);\n        await localConnection.setRemoteDescription(answer);\n\n        // Once the connection is open, message the peer\n        dataChannel.onopen = () =\u003e {\n            dataChannel.send('Hello');\n        };\n\n        // Wait for a response:\n        const message = await new Promise((resolve) =\u003e {\n            dataChannel.addEventListener('message', (event) =\u003e resolve(event.data));\n        });\n        expect(message).to.equal('Goodbye'); // \u003c-- We get our mock response!\n\n        // Assert on the messages the mock peer received:\n        expect(await mockPeer.getAllMessages()).to.deep.equal(['Hello']);\n    });\n});\n```\n\n## Documentation\n\n### Set up guide\n\nFirst, install MockRTC:\n\n```bash\nnpm install --save-dev mockrtc\n```\n\nMockRTC can be controlled both from Node.js and from inside a browser, with the same mocking API available in both environments.\n\nFor automated testing, you'll generally want to run it inside a browser. To do this, you need two things:\n\n* A MockRTC admin server, running in Node.js (v14.17.0+).\n* A MockRTC client, running in the browser, which you can use to define your mock behaviour and query the mock peer's data.\n\nFor non-browser usage, you can just use `MockRTC.getLocal()` by itself to get a MockRTC instance, and ignore the admin server completely.\n\n#### MockRTC Admin Server\n\nThe easiest way to launch an admin server for browser or remote-control usage is using the included command-line helper, like so:\n\n```\nmockrtc -c \u003ctest command\u003e\n```\n\nThis will start an admin server, run your test command, and then stop the admin server when it finishes.\n\nYou can also do this programmatically like so:\n\n```javascript\nimport * as MockRTC from 'mockrtc';\n\nconst adminServer = MockRTC.getAdminServer();\nadminServer.start().then(() =\u003e\n    console.log('Admin server started')\n);\n```\n\n#### MockRTC Browser Setup\n\nThen from inside the browser you just need to call `MockRTC.getRemote()` to get a MockRTC instance:\n\n```javascript\nimport * as MockRTC from 'mockrtc';\n\nconst mockRTC = MockRTC.getRemote();\n\n// Call .start() \u0026 .stop() between tests\n// call .buildPeer()... to configure a peer for each test.\n```\n\nNote that as this is a universal library (it works in Node.js \u0026 browsers) this code does reference some Node.js modules \u0026 globals in a couple of places. In many bundlers this will be handled automatically, but if it's not you may need to enable node polyfills for this. In Webpack that usually means enabling [node-polyfill-webpack-plugin](https://www.npmjs.com/package/node-polyfill-webpack-plugin), or in ESBuild you'll want the [`@esbuild-plugins/node-modules-polyfill`](https://www.npmjs.com/package/@esbuild-plugins/node-modules-polyfill) and [`@esbuild-plugins/node-globals-polyfill`](https://www.npmjs.com/package/@esbuild-plugins/node-globals-polyfill) plugins.\n\n#### MockRTC Non-Browser Setup\n\nYou can also use MockRTC outside the browser: either to configure and manage test peers from a Node.js process and connect using a signalling channel, or to build non-test MockRTC debugging or proxy tools.\n\nWhen doing so, you can skip the admin server entirely, and use MockRTC like so:\n\n```javascript\nimport * as MockRTC from 'mockrtc';\n\nconst mockRTC = MockRTC.getLocal();\n\n// Use exactly the same API to configure behaviour and get signalling info\n// as in the browser getRemote() case.\n```\n\n### Mocking WebRTC Traffic\n\nMockRTC provides APIs to define mock peers. Each peer has associated behaviour, defined as a series of steps, and runs each step in turn for each connection it receives.\n\nTo create a peer, use the `.buildPeer()` method on a MockRTC instance, call methods to define steps, and then call a `.thenX()` method to define the final step and create the peer itself. Here's an example:\n\n```javascript\nimport * as MockRTC from 'mockrtc';\n\nconst mockRTC = MockRTC.getRemote();\nmockRTC.start().then(() =\u003e {\n\n    const mockPeer = mockRTC.buildPeer()\n        .waitForChannel('chat-datachannel')\n        .sleep(100)\n        .send(\"hi there\")\n        .thenEcho();\n\n});\n```\n\nFor a full list of the behaviours available, see the [reference documentation](https://httptoolkit.github.io/mockrtc/interfaces/MockRTCPeerBuilder.html).\n\nOnce you have a peer configured, you can make explicit connections to it by generating an WebRTC offer, or providing a WebRTC offer yourself to get an answer. The offers \u0026 answers should be in the format of [RTCSessionDescriptions](https://developer.mozilla.org/en-US/docs/Web/API/RTCSessionDescription), as normally returned by `peerConn.createOffer()` in the browser WebRTC APIs.\n\nFor example:\n\n```javascript\n// Given a real non-mocked WebRTC browser connection:\nconst myConnection = new RTCPeerConnection();\n\n// Call create offer to get an offer description for a mocked connection:\nconst { offer: mockOffer, setAnswer } = await mockPeer.createOffer();\n\nmyConnection.setRemoteDescription(mockOffer);\nconst realAnswer = await myConnection.createAnswer();\nmyConnection.setLocalDescription(realAnswer);\n\n// Pass the real answer back to the callback provided by createOffer:\nsetAnswer(realAnswer);\n\n// -- Alternatively, MockRTC can answer an offer: --\n\nconst realOffer = await myConnection.createOffer();\nmyConnection.setLocalDescription(realOffer);\nconst { answer } = await mockPeer.answerOffer(realOffer);\nmyConnection.setRemoteDescription(answer);\n```\n\nIt's also possible to renegotiate existing connections: both methods also return a `session`, which exposes a very similar API to create and answer offers on the existing connection, but applied to the existing connection so that it's renegotiated in place, continuing the existing mock step processing.\n\n### Proxying WebRTC Traffic\n\nMockRTC can also act as a [MitM proxy](https://en.wikipedia.org/wiki/Man-in-the-middle_attack) for WebRTC connections, sitting between two peers to record or modify traffic in flight.\n\nThis works by creating two connections within MockRTC: a connection from your local client to a mock peer (the same as above) and an 'external' connection to the remote peer. External connections do nothing by default, but mock connections can be connected to them to begin proxying.\n\nThat means the connection structure for a proxied connection looks like this:\n\n```mermaid\ngraph TD\n    i[\"Our own local  connection (internal)\"] ---\n    m[/\"MockRTC mock peer connection (mock)\"/] ---\n    e[/\"MockRTC external connection (external)\"/] ---\n    r[\"The target peer's connection (remote)\"]\n```\n\nTo set this up, you need to:\n\n* Configure your mock peer to transparently proxy traffic, by using `.thenPassThrough()` when defining the peer.\n* Create a connection from your own peer (internal) to the mock peer.\n* Create a connection from the external peer to the remote peer.\n* Tell your mock peer which external connection to proxy you to, to create the mock + external connection.\n\nThis is a bit fiddly, so MockRTC includes functionality to take a connection and automatically hook all its methods so that this process happens automatically: `MockRTC.hookWebRTCConnection(realConnection, mockPeer)`.\n\nThat looks like this:\n\n```javascript\nconst mockPeer = await mockRTC.buildPeer()\n    .waitForNextMessage() // Wait for and drop the first datachannel message\n    .send('Injected message') // Send a message on every data channel\n    .thenPassThrough(); // Then proxy everything else\n\nconst localConn = new RTCPeerConnection();\n\n// The magic:\nMockRTC.hookWebRTCConnection(localConn, mockPeer);\n// ^ This redirects all connA's traffic via the mock peer, no matter who it connects to.\n\n// Normal WebRTC setup using real browser connections:\nconst localOffer = await localConn.createOffer();\nconst localDataChannel = localConn.createDataChannel(\"dataChannel\");\nlocalConn.setLocalDescription(localOffer);\n\nconst remoteConn = new RTCPeerConnection();\nremoteConn.setRemoteDescription(localOffer);\nconst remoteAnswer = await remoteConn.createAnswer();\nremoteConn.setLocalDescription(remoteAnswer);\nlocalConn.setRemoteDescription(remoteAnswer);\n\n// Once set up, send a few messages and log all received messages:\nlocalDataChannel.onopen = () =\u003e {\n    channel.addEventListener('message', ({ data }) =\u003e console.log('LOCAL:', data));\n    localDataChannel.send('local message 1');\n    localDataChannel.send('local message 2');\n};\n\nremoteConn.addEventListener('datachannel', ({ channel }) =\u003e {\n    channel.addEventListener('message', ({ data }) =\u003e console.log('REMOTE:', data));\n    channel.send(\"remote message 1\");\n    channel.send(\"remote message 2\");\n});\n```\n\nThe above prints:\n\n```\nLOCAL: MockRTC injected message\nREMOTE: local message 2\nLOCAL: remote message 1\nLOCAL: remote message 2\n```\n\nHere you can see the local connection receives the injected message, then the mock peer drops the first message from the local connection (so \"local message 1\" never arrives) and then everything else is proxied like any real connection.\n\nIf you wan to do this automatically for all WebRTC connections, you can also use the `WebRTC.hookAllWebRTC(mockPeer)` function, which will wrap the global `RTCPeerConnection` constructor to automatically apply this hook to every WebRTC connection when it's created, to redirect _all_ traffic through the given mock peer. Note that this only applies to new WebRTC connections, so this should be called before your first WebRTC connection is created.\n\n### API Reference Docs\n\nFor more details, see the [MockRTC reference docs](https://httptoolkit.github.io/mockrtc/).\n\n---\n\nHave more questions, issues or feature requests? [File an issue](https://github.com/httptoolkit/mockrtc/issues/new).\n\nYou might also be interested in scrolling through MockRTC's [test suite](https://github.com/httptoolkit/mockrtc/tree/main/test/integration), which provides a wide set of examples for all functionality.\n\n---\n\n_This‌ ‌project‌ ‌has‌ ‌received‌ ‌funding‌ ‌from‌ ‌the‌ ‌European‌ ‌Union’s‌ ‌Horizon‌ ‌2020‌‌ research‌ ‌and‌ ‌innovation‌ ‌programme‌ ‌within‌ ‌the‌ ‌framework‌ ‌of‌ ‌the‌ ‌NGI-POINTER‌‌ Project‌ ‌funded‌ ‌under‌ ‌grant‌ ‌agreement‌ ‌No‌ 871528._\n\n![The NGI logo and EU flag](./ngi-eu-footer.png)\n","funding_links":[],"categories":["TypeScript"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttptoolkit%2Fmockrtc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhttptoolkit%2Fmockrtc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhttptoolkit%2Fmockrtc/lists"}