diff --git a/packages/integration-tests/playwright.config.ts b/packages/integration-tests/playwright.config.ts index bd5710d5..7cfe53b2 100644 --- a/packages/integration-tests/playwright.config.ts +++ b/packages/integration-tests/playwright.config.ts @@ -60,34 +60,34 @@ export default defineConfig({ projects: [ { name: 'chromium', - use: { ...devices['Desktop Chrome'], headless: false }, + use: { ...devices['Desktop Chrome'] }, }, - // { - // name: 'firefox', - // use: { ...devices['Desktop Firefox'] }, - // }, - // - // { - // name: 'webkit', - // use: { ...devices['Desktop Safari'] }, - // }, - // - // { - // name: 'edge', - // use: { - // ...devices['Desktop Edge'], - // channel: 'msedge', - // }, - // }, - // - // { - // name: 'chrome', - // use: { - // ...devices['Desktop Chrome'], - // channel: 'chrome', - // }, - // }, + { + name: 'firefox', + use: { ...devices['Desktop Firefox'] }, + }, + + { + name: 'webkit', + use: { ...devices['Desktop Safari'] }, + }, + + { + name: 'edge', + use: { + ...devices['Desktop Edge'], + channel: 'msedge', + }, + }, + + { + name: 'chrome', + use: { + ...devices['Desktop Chrome'], + channel: 'chrome', + }, + }, ], /* Run your local dev server before starting the tests */ diff --git a/packages/integration-tests/src/pages/record-page.ts b/packages/integration-tests/src/pages/record-page.ts index 77e05d17..52f47cde 100644 --- a/packages/integration-tests/src/pages/record-page.ts +++ b/packages/integration-tests/src/pages/record-page.ts @@ -45,10 +45,17 @@ export class RecordPage { async flushData() { await this.page.evaluate(() => { - window.SplunkRum._processor.forceFlush() + if (window.SplunkRum) { + window.SplunkRum._processor.forceFlush() + } }) } + async getCookie(name: string) { + const cookies = await this.context.cookies() + return cookies.find((cookie) => cookie.name === name) + } + goTo(url: string) { const absoluteUrl = new URL(url, 'http://localhost:3000').toString() return this.page.goto(absoluteUrl) diff --git a/packages/web/integration-tests/tests/cookies/cookies-domain.ejs b/packages/integration-tests/src/tests/cookies/cookies-domain.ejs similarity index 100% rename from packages/web/integration-tests/tests/cookies/cookies-domain.ejs rename to packages/integration-tests/src/tests/cookies/cookies-domain.ejs diff --git a/packages/web/integration-tests/tests/cookies/cookies.ejs b/packages/integration-tests/src/tests/cookies/cookies.ejs similarity index 100% rename from packages/web/integration-tests/tests/cookies/cookies.ejs rename to packages/integration-tests/src/tests/cookies/cookies.ejs diff --git a/packages/web/integration-tests/tests/cookies/cookies.iframe.ejs b/packages/integration-tests/src/tests/cookies/cookies.iframe.ejs similarity index 100% rename from packages/web/integration-tests/tests/cookies/cookies.iframe.ejs rename to packages/integration-tests/src/tests/cookies/cookies.iframe.ejs diff --git a/packages/integration-tests/src/tests/cookies/cookies.spec.ts b/packages/integration-tests/src/tests/cookies/cookies.spec.ts new file mode 100644 index 00000000..67112cac --- /dev/null +++ b/packages/integration-tests/src/tests/cookies/cookies.spec.ts @@ -0,0 +1,85 @@ +/** + * + * Copyright 2024 Splunk Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ +import { expect } from '@playwright/test' +import { test } from '../../utils/test' + +test.describe('cookies', () => { + test('Connectivity events are captured', async ({ recordPage }) => { + await recordPage.goTo('/cookies/cookies.ejs') + + // This should create two streams of documentLoad sequences, all with the same sessionId but having + // two scriptInstances (one from parent, one from iframe) + await recordPage.waitForSpans((spans) => spans.filter((s) => s.name === 'documentFetch').length === 2) + const documentFetchSpans = recordPage.receivedSpans.filter((span) => span.name === 'documentFetch') + expect(documentFetchSpans).toHaveLength(2) + + expect(documentFetchSpans[0].tags['location.href']).toBe('http://localhost:3000/cookies/iframe.ejs') + expect(documentFetchSpans[1].tags['location.href']).toBe('http://localhost:3000/cookies/cookies.ejs') + + // same sessionId& instanceId + expect(documentFetchSpans[0].tags['splunk.rumSessionId']).toBe( + documentFetchSpans[1].tags['splunk.rumSessionId'], + ) + expect(documentFetchSpans[0].tags['browser.instance.id']).toBe( + documentFetchSpans[1].tags['browser.instance.id'], + ) + + // different scriptInstance + expect(documentFetchSpans[0].tags['splunk.scriptInstance']).not.toBe( + documentFetchSpans[1].tags['splunk.scriptInstance'], + ) + + const cookie = await recordPage.getCookie('_splunk_rum_sid') + expect(cookie).toBeTruthy() + + expect(recordPage.receivedErrorSpans).toHaveLength(0) + }) + + test('setting session cookie in iframe should work', async ({ recordPage }) => { + await recordPage.goTo('/cookies/cookies.iframe.ejs') + + await recordPage.waitForSpans((spans) => + spans.some((s) => s.name === 'documentFetch' && s.tags.app === 'iframe'), + ) + const documentFetchSpans = recordPage.receivedSpans.filter((span) => span.name === 'documentFetch') + expect(documentFetchSpans).toHaveLength(1) + expect(documentFetchSpans[0].tags['splunk.rumSessionId']).toBeTruthy() + + const cookie = await recordPage.getCookie('_splunk_rum_sid') + + expect(cookie).toBeTruthy() + expect(cookie.secure).toBe(true) + expect(cookie.sameSite).toBe('None') + }) + + test('setting cookieDomain via config sets it on subdomains also', async ({ recordPage }) => { + await recordPage.goTo(`http://127.0.0.1.nip.io:3000/cookies/cookies-domain.ejs`) + const cookie1 = await recordPage.getCookie('_splunk_rum_sid') + + expect(cookie1).toBeTruthy() + + await recordPage.goTo(`http://test.127.0.0.1.nip.io:3000/cookies/cookies-domain.ejs`) + const cookie2 = await recordPage.getCookie('_splunk_rum_sid') + + expect(cookie2).toBeTruthy() + expect(cookie1.value).toBe(cookie2.value) + expect(cookie1.domain).toBe(cookie2.domain) + + expect(recordPage.receivedErrorSpans).toHaveLength(0) + }) +}) diff --git a/packages/web/integration-tests/tests/cookies/iframe.ejs b/packages/integration-tests/src/tests/cookies/iframe.ejs similarity index 100% rename from packages/web/integration-tests/tests/cookies/iframe.ejs rename to packages/integration-tests/src/tests/cookies/iframe.ejs diff --git a/packages/web/integration-tests/tests/redacting-attributes/index.ejs b/packages/integration-tests/src/tests/redacting-attributes/index.ejs similarity index 100% rename from packages/web/integration-tests/tests/redacting-attributes/index.ejs rename to packages/integration-tests/src/tests/redacting-attributes/index.ejs diff --git a/packages/web/integration-tests/tests/cookies/cookies.spec.js b/packages/web/integration-tests/tests/cookies/cookies.spec.js deleted file mode 100644 index 2d6111eb..00000000 --- a/packages/web/integration-tests/tests/cookies/cookies.spec.js +++ /dev/null @@ -1,102 +0,0 @@ -/** - * - * Copyright 2024 Splunk Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - * - */ - -const { isBrowser } = require('../../utils/helpers') - -module.exports = { - 'afterEach': function (browser) { - browser.globals.clearReceivedSpans() - }, - 'setting session cookie should work': async function (browser) { - await browser.url(browser.globals.getUrl('/cookies/cookies.ejs')) - - // This should create two streams of documentLoad sequences, all with the same sessionId but having - // two scriptInstances (one from parent, one from iframe) - const parent = await browser.globals.findSpan( - (span) => span.name === 'documentFetch' && span.tags['location.href'].includes('cookies.ejs'), - ) - await browser.assert.ok(parent.tags['browser.instance.id']) - - await browser.assert.notEqual(parent.tags['splunk.scriptInstance'], parent.tags['splunk.rumSessionId']) - - const iframe = await browser.globals.findSpan( - (span) => span.name === 'documentFetch' && span.tags['location.href'].includes('iframe.ejs'), - ) - await browser.assert.ok(iframe.tags['splunk.rumSessionId']) - await browser.assert.notEqual(iframe.tags['splunk.scriptInstance'], iframe.tags['splunk.rumSessionId']) - - // same session id & instanceId - await browser.assert.equal(parent.tags['splunk.rumSessionId'], iframe.tags['splunk.rumSessionId']) - await browser.assert.equal(parent.tags['browser.instance.id'], iframe.tags['browser.instance.id']) - - // but different scriptInstance - await browser.assert.notEqual(parent.tags['splunk.scriptInstance'], iframe.tags['splunk.scriptInstance']) - - const cookie = await browser.getCookie('_splunk_rum_sid') - await browser.assert.ok(cookie) - // FIXME we previously tested that the cookie was marked SameSite=Strict but new session implementation - // has a race between iframes and parents from the same domain. - - await browser.globals.assertNoErrorSpans() - }, - 'setting session cookie in iframe should work': async function (browser) { - await browser.url(browser.globals.getUrl('/cookies/cookies.iframe.ejs')) - - const fetchSpan = await browser.globals.findSpan( - (span) => span.name === 'documentFetch' && span.tags.app === 'iframe', - ) - await browser.assert.ok(fetchSpan.tags['splunk.rumSessionId']) - const cookie = await browser.getCookie('_splunk_rum_sid') - await browser.assert.ok(cookie) - await browser.assert.ok(fetchSpan) - if (!isBrowser(browser, 'internet explorer') && browser.globals.enableHttps) { - await browser.assert.ok(cookie.secure) - } - - if (!isBrowser(browser, { 'internet explorer': true, 'safari': true })) { - await browser.assert.equal(cookie.sameSite, browser.globals.enableHttps ? 'None' : 'Strict') - } - }, - 'setting cookieDomain via config sets it on subdomains also': async function (browser) { - // chrome: too old to remember - // edge: doesnt' work in saucelab right now for some reason? - if (isBrowser(browser, { chrome: true, microsoftedge: true })) { - return - } - - /* - We are using nip.io to let us test subdomains not sure how reliable it is, so if - you are debugging flaky test then this should be your first guess. - cookies-domain.ejs has cookieDomain set to 127.0.0.1.nip.io, cookie set via cookieDomain - should be accessible for subdomains also so when we go to test. subdomain we should find the same - cookie. - */ - const protocol = browser.globals.enableHttps ? 'https' : 'http' - await browser.url(`${protocol}://127.0.0.1.nip.io:${browser.globals.httpPort}/cookies/cookies-domain.ejs`) - const cookie = await browser.getCookie('_splunk_rum_sid') - await browser.assert.ok(cookie) - - await browser.url(`${protocol}://test.127.0.0.1.nip.io:${browser.globals.httpPort}/cookies/cookies-domain.ejs`) - - const cookie2 = await browser.getCookie('_splunk_rum_sid') - await browser.assert.strictEqual(cookie.domain, cookie2.domain) - await browser.assert.strictEqual(cookie.value, cookie2.value) - - await browser.globals.assertNoErrorSpans() - }, -}