-
Notifications
You must be signed in to change notification settings - Fork 216
Migrate browser tests from Karma to Web Test Runner #1300
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
Merged
Merged
Changes from all commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
c345507
fixes to rollbar-test
matux 27de922
rollbar test utils
matux b51483b
closer
matux e1ba951
browser tests
matux 9daf2b9
fixed all remaining browser tests
matux f8527e6
improve comment
matux e2291c6
Update test/browser.rollbar.test.js
matux ae0e589
remove exclude
matux File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,77 @@ | ||
| import { expect } from 'chai'; | ||
| import sinon from 'sinon'; | ||
|
|
||
| import { setTimeout } from './util/timers.js'; | ||
|
|
||
| import Rollbar from '../src/browser/rollbar.js'; | ||
|
|
||
| describe('options.autoInstrument', function () { | ||
| describe('contentSecurityPolicy', function () { | ||
| let rollbar = null; | ||
|
|
||
| beforeEach(function () { | ||
| rollbar = window.rollbar = new Rollbar({ | ||
| accessToken: 'POST_CLIENT_ITEM_TOKEN', | ||
| autoInstrument: { | ||
| log: false, | ||
| contentSecurityPolicy: true, | ||
| errorOnContentSecurityPolicy: true, | ||
| }, | ||
| }); | ||
| }); | ||
|
|
||
| afterEach(function () { | ||
| window.rollbar.configure({ | ||
| autoInstrument: false, | ||
| captureUncaught: false, | ||
| }); | ||
| }); | ||
|
|
||
| it('should report content security policy errors', async function () { | ||
| const queue = rollbar.client.notifier.queue; | ||
| const queueStub = sinon.stub(queue, '_makeApiRequest'); | ||
|
|
||
| // Manually trigger a CSP violation event, | ||
| // since WTR+Mocha will capture the rejection from loadHtml. | ||
| const cspEvent = new SecurityPolicyViolationEvent( | ||
| 'securitypolicyviolation', | ||
| { | ||
| blockedURI: 'https://example.com/v3/', | ||
| violatedDirective: 'script-src', | ||
| effectiveDirective: 'script-src', | ||
| originalPolicy: "default-src 'self' 'unsafe-inline' 'unsafe-eval';", | ||
| sourceFile: window.location.href, | ||
| lineNumber: 1, | ||
| columnNumber: 1, | ||
| }, | ||
| ); | ||
|
|
||
| document.dispatchEvent(cspEvent); | ||
|
|
||
| await setTimeout(100); | ||
|
|
||
| expect(queueStub.called).to.be.true; | ||
| const item = queueStub.getCall(0).args[0]; | ||
| const message = item.body.message.body; | ||
| const telemetry = item.body.telemetry[0]; | ||
|
|
||
| expect(message).to.match(/Security Policy Violation/); | ||
| expect(message).to.match(/blockedURI: https:\/\/example.com\/v3\//); | ||
| expect(message).to.match(/violatedDirective: script-src/); | ||
| expect(message).to.match( | ||
| /originalPolicy: default-src 'self' 'unsafe-inline' 'unsafe-eval';/, | ||
| ); | ||
|
|
||
| expect(telemetry.level).to.eql('error'); | ||
| expect(telemetry.type).to.eql('log'); | ||
| expect(telemetry.body.message).to.match(/Security Policy Violation/); | ||
| expect(telemetry.body.message).to.match( | ||
| /blockedURI: https:\/\/example.com\/v3\//, | ||
| ); | ||
| expect(telemetry.body.message).to.match(/violatedDirective: script-src/); | ||
| expect(telemetry.body.message).to.match( | ||
| /originalPolicy: default-src 'self' 'unsafe-inline' 'unsafe-eval';/, | ||
| ); | ||
| }); | ||
| }); | ||
| }); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,254 @@ | ||
| import { expect } from 'chai'; | ||
| import sinon from 'sinon'; | ||
|
|
||
| import { setTimeout } from './util/timers.js'; | ||
|
|
||
| import Rollbar from '../src/browser/rollbar.js'; | ||
|
|
||
| describe('options.autoInstrument', function () { | ||
| beforeEach(function () { | ||
| window.server = sinon.createFakeServer(); | ||
| }); | ||
|
|
||
| afterEach(function () { | ||
| window.rollbar.configure({ autoInstrument: false, captureUncaught: false }); | ||
| window.server.restore(); | ||
| }); | ||
|
|
||
| function stubResponse(server) { | ||
| server.respondWith('POST', 'api/1/item', [ | ||
| 200, | ||
| { 'Content-Type': 'application/json' }, | ||
| '{"err": 0, "result":{ "uuid": "d4c7acef55bf4c9ea95e4fe9428a8287"}}', | ||
| ]); | ||
| } | ||
|
|
||
| describe('fetch', function () { | ||
| it('should add telemetry events', async function () { | ||
| const server = window.server; | ||
| expect(server).to.exist; | ||
|
|
||
| stubResponse(server); | ||
| server.requests.length = 0; | ||
|
|
||
| window.fetchStub = sinon.stub(window, 'fetch'); | ||
|
|
||
| const responseBody = JSON.stringify({ name: 'foo', password: '123456' }); | ||
| window.fetch.returns( | ||
| Promise.resolve( | ||
| new Response(responseBody, { | ||
| status: 200, | ||
| statusText: 'OK', | ||
| headers: { 'content-type': 'application/json', password: '123456' }, | ||
| }), | ||
| ), | ||
| ); | ||
|
|
||
| const rollbar = (window.rollbar = new Rollbar({ | ||
| accessToken: 'POST_CLIENT_ITEM_TOKEN', | ||
| autoInstrument: { | ||
| log: false, | ||
| network: true, | ||
| networkResponseHeaders: true, | ||
| networkResponseBody: true, | ||
| networkRequestBody: true, | ||
| networkRequestHeaders: true, | ||
| }, | ||
| })); | ||
|
|
||
| const fetchHeaders = new Headers(); | ||
| fetchHeaders.append('Content-Type', 'application/json'); | ||
| fetchHeaders.append('Secret', '123456'); | ||
|
|
||
| const fetchRequest = new Request('https://example.com/fetch-test'); | ||
| const fetchInit = { | ||
| method: 'POST', | ||
| headers: fetchHeaders, | ||
| body: JSON.stringify({ name: 'bar', secret: 'fetch post' }), | ||
| }; | ||
|
|
||
| await window | ||
| .fetch(fetchRequest, fetchInit) | ||
| .then((response) => { | ||
| // Assert that the original stream reader hasn't been read. | ||
| expect(response.bodyUsed).to.be.false; | ||
| return response.text(); | ||
| }) | ||
| .then(async (text) => { | ||
| expect(text).to.eql(responseBody); | ||
|
|
||
| rollbar.log('test'); // generate a payload to inspect | ||
|
|
||
| await setTimeout(1); | ||
|
|
||
| server.respond(); | ||
|
|
||
| expect(window.fetchStub.called).to.be.true; | ||
| expect(server.requests).to.have.lengthOf(1); | ||
| const body = JSON.parse(server.requests[0].requestBody); | ||
|
|
||
| // Verify request capture and scrubbing | ||
| expect(body.data.body.telemetry[0].body.request).to.eql( | ||
| '{"name":"bar","secret":"********"}', | ||
| ); | ||
|
|
||
| // Verify request headers capture and case-insensitive scrubbing | ||
| expect(body.data.body.telemetry[0].body.request_headers).to.eql({ | ||
| 'content-type': 'application/json', | ||
| secret: '********', | ||
| }); | ||
|
|
||
| // Verify response capture and scrubbing | ||
| expect(body.data.body.telemetry[0].body.response.body).to.eql( | ||
| '{"name":"foo","password":"********"}', | ||
| ); | ||
|
|
||
| // Verify response headers capture and case-insensitive scrubbing | ||
| expect(body.data.body.telemetry[0].body.response.headers).to.eql({ | ||
| 'content-type': 'application/json', | ||
| password: '********', | ||
| }); | ||
|
|
||
| rollbar.configure({ autoInstrument: false }); | ||
| window.fetch.restore(); | ||
| }); | ||
| }); | ||
|
|
||
| it('should report error for http 4xx when enabled', async function () { | ||
| const server = window.server; | ||
| expect(server).to.exist; | ||
|
|
||
| stubResponse(server); | ||
| server.requests.length = 0; | ||
|
|
||
| window.fetchStub = sinon.stub(window, 'fetch'); | ||
| window.fetch.returns( | ||
| Promise.resolve( | ||
| new Response(JSON.stringify({ foo: 'bar' }), { | ||
| status: 404, | ||
| statusText: 'Not Found', | ||
| headers: { 'content-type': 'application/json' }, | ||
| }), | ||
| ), | ||
| ); | ||
|
|
||
| const rollbar = (window.rollbar = new Rollbar({ | ||
| accessToken: 'POST_CLIENT_ITEM_TOKEN', | ||
| autoInstrument: { | ||
| log: false, | ||
| network: true, | ||
| networkErrorOnHttp4xx: true, | ||
| }, | ||
| })); | ||
|
|
||
| const fetchHeaders = new Headers(); | ||
| fetchHeaders.append('Content-Type', 'application/json'); | ||
|
|
||
| const fetchRequest = new Request('https://example.com/xhr-test'); | ||
| const fetchInit = { | ||
| method: 'POST', | ||
| headers: fetchHeaders, | ||
| body: JSON.stringify({ foo: 'bar' }), | ||
| }; | ||
|
|
||
| await window.fetch(fetchRequest, fetchInit).then(async (_response) => { | ||
| await setTimeout(1); | ||
|
|
||
| server.respond(); | ||
|
|
||
| expect(server.requests).to.have.lengthOf(1); | ||
| const body = JSON.parse(server.requests[0].requestBody); | ||
|
|
||
| expect(body.data.body.trace.exception.message).to.eql( | ||
| 'HTTP request failed with Status 404', | ||
| ); | ||
|
|
||
| // Just knowing a stack is present is enough for this test. | ||
| expect(body.data.body.trace.frames).to.have.lengthOf.above(1); | ||
|
|
||
| rollbar.configure({ autoInstrument: false }); | ||
| window.fetch.restore(); | ||
| }); | ||
| }); | ||
|
|
||
| it('should add telemetry headers when fetch Headers object is undefined', async function () { | ||
| const server = window.server; | ||
| expect(server).to.exist; | ||
|
|
||
| stubResponse(server); | ||
| server.requests.length = 0; | ||
|
|
||
| window.fetchStub = sinon.stub(window, 'fetch'); | ||
|
|
||
| const readableStream = new ReadableStream({ | ||
| start(controller) { | ||
| controller.enqueue( | ||
| JSON.stringify({ name: 'foo', password: '123456' }), | ||
| ); | ||
| controller.close(); | ||
| }, | ||
| }); | ||
|
|
||
| window.fetch.returns( | ||
| Promise.resolve( | ||
| new Response(readableStream, { | ||
| status: 200, | ||
| statusText: 'OK', | ||
| headers: { 'content-type': 'application/json', password: '123456' }, | ||
| }), | ||
| ), | ||
| ); | ||
|
|
||
| const rollbar = (window.rollbar = new Rollbar({ | ||
| accessToken: 'POST_CLIENT_ITEM_TOKEN', | ||
| autoInstrument: { | ||
| log: false, | ||
| network: true, | ||
| networkResponseHeaders: true, | ||
| networkRequestHeaders: true, | ||
| }, | ||
| })); | ||
|
|
||
| // Remove Headers from window object | ||
| const originalHeaders = window.Headers; | ||
| delete window.Headers; | ||
|
|
||
| const fetchRequest = new Request('https://example.com/xhr-test'); | ||
| const fetchInit = { | ||
| method: 'POST', | ||
| headers: { 'Content-Type': 'application/json', Secret: '123456' }, | ||
| body: JSON.stringify({ name: 'bar', secret: 'xhr post' }), | ||
| }; | ||
|
|
||
| await window.fetch(fetchRequest, fetchInit).then(async (response) => { | ||
| rollbar.log('test'); // generate a payload to inspect | ||
|
|
||
| await setTimeout(1); | ||
|
|
||
| server.respond(); | ||
|
|
||
| expect(server.requests).to.have.lengthOf(1); | ||
| const body = JSON.parse(server.requests[0].requestBody); | ||
|
|
||
| // Verify request headers capture and case-insensitive scrubbing | ||
| expect(body.data.body.telemetry[0].body.request_headers).to.eql({ | ||
| 'content-type': 'application/json', | ||
| secret: '********', | ||
| }); | ||
|
|
||
| // Verify response headers capture and case-insensitive scrubbing | ||
| expect(body.data.body.telemetry[0].body.response.headers).to.eql({ | ||
| 'content-type': 'application/json', | ||
| password: '********', | ||
| }); | ||
|
|
||
| // Assert that the original stream reader hasn't been read. | ||
| expect(response.bodyUsed).to.be.false; | ||
|
|
||
| rollbar.configure({ autoInstrument: false }); | ||
| window.fetch.restore(); | ||
| window.Headers = originalHeaders; | ||
| }); | ||
| }); | ||
| }); | ||
| }); |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Refer to this comment for more details: https://github.com/rollbar/rollbar.js/pull/1300/files#r2331149823