feat(tracker): safety wrap for angular, new performance/lag display system
* feat(tracker): make message commits low priority (possibly improve browser lags display), add safe polyfill for env methods hijacked by angular * feat(tracker): add bun.sh support * feat(tracker): add bun.sh support to actions * feat(tracker): add bun.sh support to actions * feat(tracker): add bun.sh support to actions * fix(tracker): fix e2e test workflow file * fix(tracker): fix e2e test workflow file * fix(tracker): fix test workflow file * fix(tracker): fix requestIdleCallback check, add test cov for new utilities * fix(tracker): fix eslint complains * fix(ui): fix yarn bug * fix(ui): fix yarn bug * fix(ui): fix yarn bug * fix(ui): fix ci test * fix(ui): fix ci test * fix(ui): fix ci test * fix(ui): fix ci test * fix(ui): fix ci test * fix(ui): fix ci test * fix(ui): fix ci test * fix(ui): debug logs * fix(ui): debug logs * fix(ui): debug logs * fix(ui): debug logs * fix(ui): remove logs * fix(ui): fix waiting for ui * fix(ui): fix? * fix(ui): fix? * fix(ui): fix? * fix(ui): fix? * fix(ui): fix! * fix(ui): fix! * fix(ui): finally
This commit is contained in:
parent
e6957d631c
commit
e3893b92ce
21 changed files with 435 additions and 116 deletions
30
.github/workflows/tracker-tests.yaml
vendored
30
.github/workflows/tracker-tests.yaml
vendored
|
|
@ -17,8 +17,11 @@ jobs:
|
|||
name: Build and test Tracker
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [ 16.x ]
|
||||
node-version: [ 18.x ]
|
||||
steps:
|
||||
- uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
|
|
@ -28,7 +31,7 @@ jobs:
|
|||
uses: actions/cache@v3
|
||||
with:
|
||||
path: tracker/tracker/node_modules
|
||||
key: ${{ runner.OS }}-test_tracker_build-${{ hashFiles('**/yarn.lock') }}
|
||||
key: ${{ runner.OS }}-test_tracker_build-${{ hashFiles('**/bun.lockb') }}
|
||||
restore-keys: |
|
||||
test_tracker_build{{ runner.OS }}-build-
|
||||
test_tracker_build{{ runner.OS }}-
|
||||
|
|
@ -36,27 +39,34 @@ jobs:
|
|||
uses: actions/cache@v3
|
||||
with:
|
||||
path: tracker/tracker-assist/node_modules
|
||||
key: ${{ runner.OS }}-test_tracker_build-${{ hashFiles('**/yarn.lock') }}
|
||||
key: ${{ runner.OS }}-test_tracker_build-${{ hashFiles('**/bun.lockb') }}
|
||||
restore-keys: |
|
||||
test_tracker_build{{ runner.OS }}-build-
|
||||
test_tracker_build{{ runner.OS }}-
|
||||
- name: Setup Testing packages
|
||||
run: |
|
||||
cd tracker/tracker
|
||||
npm i -g yarn
|
||||
yarn
|
||||
- name: Setup Testing packages
|
||||
bun install
|
||||
- name: (TA) Setup Testing packages
|
||||
run: |
|
||||
cd tracker/tracker-assist
|
||||
yarn
|
||||
bun install
|
||||
- name: Jest tests
|
||||
run: |
|
||||
cd tracker/tracker
|
||||
yarn test:ci
|
||||
- name: Jest tests
|
||||
bun run test:ci
|
||||
- name: Building test
|
||||
run: |
|
||||
cd tracker/tracker
|
||||
bun run build
|
||||
- name: (TA) Jest tests
|
||||
run: |
|
||||
cd tracker/tracker-assist
|
||||
yarn test:ci
|
||||
bun run test:ci
|
||||
- name: (TA) Building test
|
||||
run: |
|
||||
cd tracker/tracker-assist
|
||||
bun run build
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
|
|
|
|||
46
.github/workflows/ui-tests.js.yml
vendored
46
.github/workflows/ui-tests.js.yml
vendored
|
|
@ -27,8 +27,11 @@ jobs:
|
|||
name: Build and test Tracker plus Replayer
|
||||
strategy:
|
||||
matrix:
|
||||
node-version: [ 16.x ]
|
||||
node-version: [ 18.x ]
|
||||
steps:
|
||||
- uses: oven-sh/setup-bun@v1
|
||||
with:
|
||||
bun-version: latest
|
||||
- uses: actions/checkout@v3
|
||||
- name: Use Node.js ${{ matrix.node-version }}
|
||||
uses: actions/setup-node@v3
|
||||
|
|
@ -38,18 +41,18 @@ jobs:
|
|||
uses: actions/cache@v3
|
||||
with:
|
||||
path: tracker/tracker/node_modules
|
||||
key: ${{ runner.OS }}-test_tracker_build-${{ hashFiles('tracker/tracker/yarn.lock') }}
|
||||
key: ${{ runner.OS }}-test_tracker_build-${{ hashFiles('tracker/tracker/bun.lockb') }}
|
||||
restore-keys: |
|
||||
test_tracker_build-{{ runner.OS }}-build-
|
||||
test_tracker_build-{{ runner.OS }}-
|
||||
- name: Setup Testing packages
|
||||
run: |
|
||||
cd tracker/tracker
|
||||
yarn
|
||||
bun install
|
||||
- name: Build tracker inst
|
||||
run: |
|
||||
cd tracker/tracker
|
||||
yarn build
|
||||
bun run build
|
||||
- name: Setup Testing UI Env
|
||||
run: |
|
||||
cd tracker/tracker-testing-playground
|
||||
|
|
@ -67,10 +70,6 @@ jobs:
|
|||
run: |
|
||||
cd tracker/tracker-testing-playground
|
||||
yarn
|
||||
- name: Run testing frontend
|
||||
run: |
|
||||
cd tracker/tracker-testing-playground
|
||||
yarn start &> ui.log &
|
||||
- name: Cache node modules
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
|
|
@ -96,39 +95,50 @@ jobs:
|
|||
echo "MINIO_USE_SSL = ''" >> .env
|
||||
echo "MINIO_ACCESS_KEY = ''" >> .env
|
||||
echo "MINIO_SECRET_KEY = ''" >> .env
|
||||
echo "VERSION = '1.9.0'" >> .env
|
||||
echo "TRACKER_VERSION = '4.0.0'" >> .env
|
||||
echo "VERSION = '1.15.0'" >> .env
|
||||
echo "TRACKER_VERSION = '10.0.0'" >> .env
|
||||
echo "COMMIT_HASH = 'dev'" >> .env
|
||||
echo "{ \"account\": \"$CY_ACC\", \"password\": \"$CY_PASS\" }" >> cypress.env.json
|
||||
- name: Setup packages
|
||||
run: |
|
||||
cd frontend
|
||||
yarn
|
||||
npm install --legacy-peer-deps
|
||||
- name: Run unit tests
|
||||
run: |
|
||||
cd frontend
|
||||
yarn test
|
||||
npm run test:ci
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
token: ${{ secrets.CODECOV_TOKEN }}
|
||||
flags: ui
|
||||
name: ui
|
||||
- name: Wait for Testing Frontend
|
||||
- name: Run testing frontend
|
||||
run: |
|
||||
cd tracker/tracker-testing-playground
|
||||
yarn start &> testing.log &
|
||||
echo "Started"
|
||||
npm i -g wait-on
|
||||
echo "Got wait on"
|
||||
sleep 30
|
||||
cat testing.log
|
||||
npx wait-on http://localhost:3000
|
||||
echo "Done"
|
||||
timeout-minutes: 4
|
||||
- name: Run Frontend
|
||||
run: |
|
||||
cd frontend
|
||||
yarn start &> frontend.log &
|
||||
- name: Wait for frontend
|
||||
run: |
|
||||
cd frontend
|
||||
bun start &> frontend.log &
|
||||
echo "Started"
|
||||
sleep 30
|
||||
cat frontend.log
|
||||
npx wait-on http://0.0.0.0:3333
|
||||
echo "Done"
|
||||
timeout-minutes: 4
|
||||
- name: (Chrome) Run visual tests
|
||||
run: |
|
||||
cd frontend
|
||||
yarn cy:test
|
||||
npm run cy:test
|
||||
# firefox have different viewport somehow
|
||||
# - name: (Firefox) Run visual tests
|
||||
# run: yarn cy:test-firefox
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ type Entries<T> = {
|
|||
[K in keyof T]: [K, T[K]];
|
||||
}[keyof T][];
|
||||
|
||||
export default class LSCache<G extends Record<string, boolean | number | string> {
|
||||
export default class LSCache<G extends Record<string, boolean | number | string>> {
|
||||
constructor(private state: SimpleState<G>, private keyMap: Record<keyof Partial<G>, string>) {
|
||||
}
|
||||
update(newState: Partial<G>) {
|
||||
|
|
|
|||
|
|
@ -1,44 +0,0 @@
|
|||
describe('Testing general stability', {
|
||||
viewportHeight: 900,
|
||||
viewportWidth: 1400,
|
||||
}, () => {
|
||||
it('Checking if app will crash', () => {
|
||||
cy.clearCookies()
|
||||
cy.clearAllSessionStorage()
|
||||
cy.clearAllCookies()
|
||||
cy.clearAllLocalStorage()
|
||||
|
||||
cy.intercept('**/api/account').as('getAccount');
|
||||
|
||||
cy.visit('/')
|
||||
cy.get('[data-test-id=login]').type(Cypress.env('account').replaceAll('"', ''));
|
||||
cy.get('[data-test-id=password]').type(Cypress.env('password').replaceAll('"', ''));
|
||||
cy.get('[data-test-id=log-button]').click();
|
||||
cy.wait('@getAccount')
|
||||
|
||||
Cypress.on('uncaught:exception', (err, runnable) => {
|
||||
return false
|
||||
})
|
||||
|
||||
cy.get(':nth-child(1) > .ant-menu-item-group-title > .ant-typography').should('be.visible')
|
||||
|
||||
cy.visit('/5/dashboard')
|
||||
cy.wait(500)
|
||||
cy.get('input[name="dashboardsSearch"]').should('be.visible')
|
||||
|
||||
cy.visit('/client/account')
|
||||
|
||||
cy.get(':nth-child(2) > .profileSettings-module__left--D4pCi > .profileSettings-module__info--DhVpL').should('be.visible')
|
||||
|
||||
cy.get('.ant-menu-item-group-list > :nth-child(2)').click()
|
||||
cy.wait(250)
|
||||
cy.get('.text-2xl > div').should('be.visible')
|
||||
cy.get('.ant-menu-item-group-list > :nth-child(3)').click()
|
||||
cy.get('.ant-menu-item-group-list > :nth-child(4)').click()
|
||||
cy.get('.text-base').should('be.visible')
|
||||
|
||||
cy.get('.ant-menu-item-group-title').should('be.visible')
|
||||
|
||||
// if test has not failed, we assume that app is not crashed (so far)
|
||||
})
|
||||
})
|
||||
|
|
@ -146,6 +146,16 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/code-frame@npm:^7.22.13":
|
||||
version: 7.22.13
|
||||
resolution: "@babel/code-frame@npm:7.22.13"
|
||||
dependencies:
|
||||
"@babel/highlight": ^7.22.13
|
||||
chalk: ^2.4.2
|
||||
checksum: f4cc8ae1000265677daf4845083b72f88d00d311adb1a93c94eb4b07bf0ed6828a81ae4ac43ee7d476775000b93a28a9cddec18fbdc5796212d8dcccd5de72bd
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/compat-data@npm:^7.17.7, @babel/compat-data@npm:^7.20.1, @babel/compat-data@npm:^7.20.5":
|
||||
version: 7.20.10
|
||||
resolution: "@babel/compat-data@npm:7.20.10"
|
||||
|
|
@ -220,6 +230,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-annotate-as-pure@npm:^7.22.5":
|
||||
version: 7.22.5
|
||||
resolution: "@babel/helper-annotate-as-pure@npm:7.22.5"
|
||||
dependencies:
|
||||
"@babel/types": ^7.22.5
|
||||
checksum: 5a80dc364ddda26b334bbbc0f6426cab647381555ef7d0cd32eb284e35b867c012ce6ce7d52a64672ed71383099c99d32765b3d260626527bb0e3470b0f58e45
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-builder-binary-assignment-operator-visitor@npm:^7.18.6":
|
||||
version: 7.18.9
|
||||
resolution: "@babel/helper-builder-binary-assignment-operator-visitor@npm:7.18.9"
|
||||
|
|
@ -263,6 +282,25 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-create-class-features-plugin@npm:^7.21.0":
|
||||
version: 7.22.15
|
||||
resolution: "@babel/helper-create-class-features-plugin@npm:7.22.15"
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure": ^7.22.5
|
||||
"@babel/helper-environment-visitor": ^7.22.5
|
||||
"@babel/helper-function-name": ^7.22.5
|
||||
"@babel/helper-member-expression-to-functions": ^7.22.15
|
||||
"@babel/helper-optimise-call-expression": ^7.22.5
|
||||
"@babel/helper-replace-supers": ^7.22.9
|
||||
"@babel/helper-skip-transparent-expression-wrappers": ^7.22.5
|
||||
"@babel/helper-split-export-declaration": ^7.22.6
|
||||
semver: ^6.3.1
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0
|
||||
checksum: 2ae5759fe8845fda99b34f2ba6cd0794fc860213d14c93a87aa9180960252bce621157a79c373b7fbb423b25a55fb0e20eae0d5f8e4ad5ef22dc70e7c2af3805
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-create-regexp-features-plugin@npm:^7.18.6, @babel/helper-create-regexp-features-plugin@npm:^7.20.5":
|
||||
version: 7.20.5
|
||||
resolution: "@babel/helper-create-regexp-features-plugin@npm:7.20.5"
|
||||
|
|
@ -316,6 +354,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-environment-visitor@npm:^7.22.20, @babel/helper-environment-visitor@npm:^7.22.5":
|
||||
version: 7.22.20
|
||||
resolution: "@babel/helper-environment-visitor@npm:7.22.20"
|
||||
checksum: e762c2d8f5d423af89bd7ae9abe35bd4836d2eb401af868a63bbb63220c513c783e25ef001019418560b3fdc6d9a6fb67e6c0b650bcdeb3a2ac44b5c3d2bdd94
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-explode-assignable-expression@npm:^7.18.6":
|
||||
version: 7.18.6
|
||||
resolution: "@babel/helper-explode-assignable-expression@npm:7.18.6"
|
||||
|
|
@ -335,6 +380,16 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-function-name@npm:^7.22.5":
|
||||
version: 7.23.0
|
||||
resolution: "@babel/helper-function-name@npm:7.23.0"
|
||||
dependencies:
|
||||
"@babel/template": ^7.22.15
|
||||
"@babel/types": ^7.23.0
|
||||
checksum: d771dd1f3222b120518176733c52b7cadac1c256ff49b1889dbbe5e3fed81db855b8cc4e40d949c9d3eae0e795e8229c1c8c24c0e83f27cfa6ee3766696c6428
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-hoist-variables@npm:^7.18.6":
|
||||
version: 7.18.6
|
||||
resolution: "@babel/helper-hoist-variables@npm:7.18.6"
|
||||
|
|
@ -353,6 +408,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-member-expression-to-functions@npm:^7.22.15":
|
||||
version: 7.23.0
|
||||
resolution: "@babel/helper-member-expression-to-functions@npm:7.23.0"
|
||||
dependencies:
|
||||
"@babel/types": ^7.23.0
|
||||
checksum: b810daddf093ffd0802f1429052349ed9ea08ef7d0c56da34ffbcdecbdafac86f95bdea2fe30e0e0e629febc7dd41b56cb5eacc10d1a44336d37b755dac31fa4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-module-imports@npm:^7.10.4, @babel/helper-module-imports@npm:^7.12.13, @babel/helper-module-imports@npm:^7.16.7, @babel/helper-module-imports@npm:^7.18.6":
|
||||
version: 7.18.6
|
||||
resolution: "@babel/helper-module-imports@npm:7.18.6"
|
||||
|
|
@ -387,6 +451,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-optimise-call-expression@npm:^7.22.5":
|
||||
version: 7.22.5
|
||||
resolution: "@babel/helper-optimise-call-expression@npm:7.22.5"
|
||||
dependencies:
|
||||
"@babel/types": ^7.22.5
|
||||
checksum: 31b41a764fc3c585196cf5b776b70cf4705c132e4ce9723f39871f215f2ddbfb2e28a62f9917610f67c8216c1080482b9b05f65dd195dae2a52cef461f2ac7b8
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-plugin-utils@npm:7.10.4":
|
||||
version: 7.10.4
|
||||
resolution: "@babel/helper-plugin-utils@npm:7.10.4"
|
||||
|
|
@ -429,6 +502,19 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-replace-supers@npm:^7.22.9":
|
||||
version: 7.22.20
|
||||
resolution: "@babel/helper-replace-supers@npm:7.22.20"
|
||||
dependencies:
|
||||
"@babel/helper-environment-visitor": ^7.22.20
|
||||
"@babel/helper-member-expression-to-functions": ^7.22.15
|
||||
"@babel/helper-optimise-call-expression": ^7.22.5
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0
|
||||
checksum: 6b0858811ad46873817c90c805015d63300e003c5a85c147a17d9845fa2558a02047c3cc1f07767af59014b2dd0fa75b503e5bc36e917f360e9b67bb6f1e79f4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-simple-access@npm:^7.20.2":
|
||||
version: 7.20.2
|
||||
resolution: "@babel/helper-simple-access@npm:7.20.2"
|
||||
|
|
@ -447,6 +533,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-skip-transparent-expression-wrappers@npm:^7.22.5":
|
||||
version: 7.22.5
|
||||
resolution: "@babel/helper-skip-transparent-expression-wrappers@npm:7.22.5"
|
||||
dependencies:
|
||||
"@babel/types": ^7.22.5
|
||||
checksum: ab7fa2aa709ab49bb8cd86515a1e715a3108c4bb9a616965ba76b43dc346dee66d1004ccf4d222b596b6224e43e04cbc5c3a34459501b388451f8c589fbc3691
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-split-export-declaration@npm:^7.18.6":
|
||||
version: 7.18.6
|
||||
resolution: "@babel/helper-split-export-declaration@npm:7.18.6"
|
||||
|
|
@ -456,6 +551,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-split-export-declaration@npm:^7.22.6":
|
||||
version: 7.22.6
|
||||
resolution: "@babel/helper-split-export-declaration@npm:7.22.6"
|
||||
dependencies:
|
||||
"@babel/types": ^7.22.5
|
||||
checksum: d83e4b623eaa9622c267d3c83583b72f3aac567dc393dda18e559d79187961cb29ae9c57b2664137fc3d19508370b12ec6a81d28af73a50e0846819cb21c6e44
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-string-parser@npm:^7.19.4":
|
||||
version: 7.19.4
|
||||
resolution: "@babel/helper-string-parser@npm:7.19.4"
|
||||
|
|
@ -463,6 +567,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-string-parser@npm:^7.22.5":
|
||||
version: 7.22.5
|
||||
resolution: "@babel/helper-string-parser@npm:7.22.5"
|
||||
checksum: 6b0ff8af724377ec41e5587fffa7605198da74cb8e7d8d48a36826df0c0ba210eb9fedb3d9bef4d541156e0bd11040f021945a6cbb731ccec4aefb4affa17aa4
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-validator-identifier@npm:^7.18.6, @babel/helper-validator-identifier@npm:^7.19.1":
|
||||
version: 7.19.1
|
||||
resolution: "@babel/helper-validator-identifier@npm:7.19.1"
|
||||
|
|
@ -470,6 +581,13 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-validator-identifier@npm:^7.22.20":
|
||||
version: 7.22.20
|
||||
resolution: "@babel/helper-validator-identifier@npm:7.22.20"
|
||||
checksum: dcad63db345fb110e032de46c3688384b0008a42a4845180ce7cd62b1a9c0507a1bed727c4d1060ed1a03ae57b4d918570259f81724aaac1a5b776056f37504e
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/helper-validator-option@npm:^7.18.6":
|
||||
version: 7.18.6
|
||||
resolution: "@babel/helper-validator-option@npm:7.18.6"
|
||||
|
|
@ -511,6 +629,17 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/highlight@npm:^7.22.13":
|
||||
version: 7.22.20
|
||||
resolution: "@babel/highlight@npm:7.22.20"
|
||||
dependencies:
|
||||
"@babel/helper-validator-identifier": ^7.22.20
|
||||
chalk: ^2.4.2
|
||||
js-tokens: ^4.0.0
|
||||
checksum: f3c3a193afad23434297d88e81d1d6c0c2cf02423de2139ada7ce0a7fc62d8559abf4cc996533c1a9beca7fc990010eb8d544097f75e818ac113bf39ed810aa2
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/node@npm:^7.16.8":
|
||||
version: 7.20.7
|
||||
resolution: "@babel/node@npm:7.20.7"
|
||||
|
|
@ -538,6 +667,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/parser@npm:^7.22.15":
|
||||
version: 7.23.0
|
||||
resolution: "@babel/parser@npm:7.23.0"
|
||||
bin:
|
||||
parser: ./bin/babel-parser.js
|
||||
checksum: ab4ea9360ed4ba3c728c5a9bf33035103ebde20a7e943c4ae1d42becb02a313d731d12a93c795c5a19777031e4022e64b92a52262eda902522a1a18649826283
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:^7.18.6":
|
||||
version: 7.18.6
|
||||
resolution: "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@npm:7.18.6"
|
||||
|
|
@ -779,6 +917,20 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/plugin-proposal-private-property-in-object@npm:^7.21.11":
|
||||
version: 7.21.11
|
||||
resolution: "@babel/plugin-proposal-private-property-in-object@npm:7.21.11"
|
||||
dependencies:
|
||||
"@babel/helper-annotate-as-pure": ^7.18.6
|
||||
"@babel/helper-create-class-features-plugin": ^7.21.0
|
||||
"@babel/helper-plugin-utils": ^7.20.2
|
||||
"@babel/plugin-syntax-private-property-in-object": ^7.14.5
|
||||
peerDependencies:
|
||||
"@babel/core": ^7.0.0-0
|
||||
checksum: 3c8c9ea175101b1cbb2b0e8fee20fcbdd03eb0700d3581aa826ac3573c9b002f39b1512c2af9fd1903ff921bcc864da95ad3cdeba53c9fbcfb3dc23916eacf47
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/plugin-proposal-unicode-property-regex@npm:^7.18.6, @babel/plugin-proposal-unicode-property-regex@npm:^7.4.4":
|
||||
version: 7.18.6
|
||||
resolution: "@babel/plugin-proposal-unicode-property-regex@npm:7.18.6"
|
||||
|
|
@ -1737,6 +1889,17 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/template@npm:^7.22.15":
|
||||
version: 7.22.15
|
||||
resolution: "@babel/template@npm:7.22.15"
|
||||
dependencies:
|
||||
"@babel/code-frame": ^7.22.13
|
||||
"@babel/parser": ^7.22.15
|
||||
"@babel/types": ^7.22.15
|
||||
checksum: 9312edd37cf1311d738907003f2aa321a88a42ba223c69209abe4d7111db019d321805504f606c7fd75f21c6cf9d24d0a8223104cd21ebd207e241b6c551f454
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/traverse@npm:^7.1.0, @babel/traverse@npm:^7.1.6, @babel/traverse@npm:^7.12.11, @babel/traverse@npm:^7.12.9, @babel/traverse@npm:^7.13.0, @babel/traverse@npm:^7.20.10, @babel/traverse@npm:^7.20.12, @babel/traverse@npm:^7.20.5, @babel/traverse@npm:^7.20.7, @babel/traverse@npm:^7.7.2":
|
||||
version: 7.20.12
|
||||
resolution: "@babel/traverse@npm:7.20.12"
|
||||
|
|
@ -1766,6 +1929,17 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@babel/types@npm:^7.22.15, @babel/types@npm:^7.22.5, @babel/types@npm:^7.23.0":
|
||||
version: 7.23.0
|
||||
resolution: "@babel/types@npm:7.23.0"
|
||||
dependencies:
|
||||
"@babel/helper-string-parser": ^7.22.5
|
||||
"@babel/helper-validator-identifier": ^7.22.20
|
||||
to-fast-properties: ^2.0.0
|
||||
checksum: 70e4db41acb6793d0eb8d81a2fa88f19ee661219b84bd5f703dbdb54eb3a4d3c0dfc55e69034c945b479df9f43fd4b1376480aaccfc19797ce5af1c5d2576b36
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"@base2/pretty-print-object@npm:1.0.1":
|
||||
version: 1.0.1
|
||||
resolution: "@base2/pretty-print-object@npm:1.0.1"
|
||||
|
|
@ -8044,7 +8218,7 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"chalk@npm:^2.0.0, chalk@npm:^2.0.1, chalk@npm:^2.4.1":
|
||||
"chalk@npm:^2.0.0, chalk@npm:^2.0.1, chalk@npm:^2.4.1, chalk@npm:^2.4.2":
|
||||
version: 2.4.2
|
||||
resolution: "chalk@npm:2.4.2"
|
||||
dependencies:
|
||||
|
|
@ -17558,6 +17732,7 @@ __metadata:
|
|||
"@babel/plugin-proposal-class-properties": ^7.17.12
|
||||
"@babel/plugin-proposal-decorators": ^7.17.12
|
||||
"@babel/plugin-proposal-private-methods": ^7.10.4
|
||||
"@babel/plugin-proposal-private-property-in-object": ^7.21.11
|
||||
"@babel/plugin-syntax-bigint": ^7.8.3
|
||||
"@babel/plugin-transform-runtime": ^7.17.12
|
||||
"@babel/preset-env": ^7.17.12
|
||||
|
|
@ -21852,6 +22027,15 @@ __metadata:
|
|||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"semver@npm:^6.3.1":
|
||||
version: 6.3.1
|
||||
resolution: "semver@npm:6.3.1"
|
||||
bin:
|
||||
semver: bin/semver.js
|
||||
checksum: e3d79b609071caa78bcb6ce2ad81c7966a46a7431d9d58b8800cfa9cb6a63699b3899a0e4bcce36167a284578212d9ae6942b6929ba4aa5015c079a67751d42d
|
||||
languageName: node
|
||||
linkType: hard
|
||||
|
||||
"semver@npm:^7.5.3":
|
||||
version: 7.5.4
|
||||
resolution: "semver@npm:7.5.4"
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ then
|
|||
pwd
|
||||
cd tracker/tracker
|
||||
|
||||
npm run lint-front
|
||||
bun run lint-front
|
||||
|
||||
cd ../../
|
||||
fi
|
||||
|
|
@ -17,7 +17,7 @@ then
|
|||
echo "tracker-assist"
|
||||
cd tracker/tracker-assist
|
||||
|
||||
npm run lint-front
|
||||
bun run lint-front
|
||||
|
||||
cd ../../
|
||||
fi
|
||||
|
|
|
|||
BIN
tracker/tracker-assist/bun.lockb
Executable file
BIN
tracker/tracker-assist/bun.lockb
Executable file
Binary file not shown.
|
|
@ -22,7 +22,7 @@
|
|||
"zustand": "^4.1.1"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "HOST=0.0.0.0 react-scripts start",
|
||||
"start": "HOST=0.0.0.0 react-scripts --openssl-legacy-provider start",
|
||||
"build": "NODE_OPTIONS=--openssl-legacy-provider react-scripts build",
|
||||
"test": "react-scripts test",
|
||||
"eject": "react-scripts eject"
|
||||
|
|
|
|||
|
|
@ -2,6 +2,10 @@
|
|||
|
||||
The main package of the [OpenReplay](https://openreplay.com/) tracker.
|
||||
|
||||
## Development & Contribution
|
||||
|
||||
Please use [bun](https://bun.sh/) to install and build this library. Any submitted pull request must pass **all tests** and should have positive test coverage diff %.
|
||||
|
||||
## Documentation
|
||||
|
||||
For launch options and available public methods, [refer to the documentation](https://docs.openreplay.com/installation/javascript-sdk#options)
|
||||
|
|
|
|||
BIN
tracker/tracker/bun.lockb
Executable file
BIN
tracker/tracker/bun.lockb
Executable file
Binary file not shown.
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "@openreplay/tracker",
|
||||
"description": "The OpenReplay tracker main package",
|
||||
"version": "10.0.0",
|
||||
"version": "10.0.1-1",
|
||||
"keywords": [
|
||||
"logging",
|
||||
"replay"
|
||||
|
|
@ -19,13 +19,13 @@
|
|||
"tscRun": "tsc -b src/main && tsc -b src/webworker && tsc --project src/main/tsconfig-cjs.json",
|
||||
"rollup": "rollup --config rollup.config.js",
|
||||
"compile": "node --experimental-modules --experimental-json-modules scripts/compile.cjs",
|
||||
"build": "npm run clean && npm run tscRun && npm run rollup && npm run compile",
|
||||
"build": "bun run clean && bun run tscRun && bun run rollup && bun run compile",
|
||||
"prepare": "cd ../../ && husky install tracker/.husky/",
|
||||
"lint-front": "lint-staged",
|
||||
"test": "jest --coverage=false",
|
||||
"test:ci": "jest --coverage=true",
|
||||
"postversion": "npm run build",
|
||||
"prepublishOnly": "npm run build"
|
||||
"postversion": "bun run build",
|
||||
"prepublishOnly": "bun run build"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.10.2",
|
||||
|
|
|
|||
|
|
@ -1,6 +1,14 @@
|
|||
import type Message from './messages.gen.js'
|
||||
import { Timestamp, Metadata, UserID, Type as MType, TabChange, TabData } from './messages.gen.js'
|
||||
import { now, adjustTimeOrigin, deprecationWarn, inIframe } from '../utils.js'
|
||||
import {
|
||||
now,
|
||||
adjustTimeOrigin,
|
||||
deprecationWarn,
|
||||
inIframe,
|
||||
createEventListener,
|
||||
deleteEventListener,
|
||||
requestIdleCb,
|
||||
} from '../utils.js'
|
||||
import Nodes from './nodes.js'
|
||||
import Observer from './observer/top_observer.js'
|
||||
import Sanitizer from './sanitizer.js'
|
||||
|
|
@ -338,12 +346,15 @@ export default class App {
|
|||
}
|
||||
|
||||
private commit(): void {
|
||||
if (this.worker && this.messages.length) {
|
||||
this.messages.unshift(TabData(this.session.getTabId()))
|
||||
this.messages.unshift(Timestamp(this.timestamp()))
|
||||
this.worker.postMessage(this.messages)
|
||||
this.commitCallbacks.forEach((cb) => cb(this.messages))
|
||||
this.messages.length = 0
|
||||
if (this.worker !== undefined && this.messages.length) {
|
||||
requestIdleCb(() => {
|
||||
this.messages.unshift(TabData(this.session.getTabId()))
|
||||
this.messages.unshift(Timestamp(this.timestamp()))
|
||||
// ? why I need to do this?
|
||||
this.worker!.postMessage(this.messages)
|
||||
this.commitCallbacks.forEach((cb) => cb(this.messages))
|
||||
this.messages.length = 0
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -397,8 +408,14 @@ export default class App {
|
|||
if (useSafe) {
|
||||
listener = this.safe(listener)
|
||||
}
|
||||
this.attachStartCallback(() => target?.addEventListener(type, listener, useCapture), useSafe)
|
||||
this.attachStopCallback(() => target?.removeEventListener(type, listener, useCapture), useSafe)
|
||||
this.attachStartCallback(
|
||||
() => (target ? createEventListener(target, type, listener, useCapture) : null),
|
||||
useSafe,
|
||||
)
|
||||
this.attachStopCallback(
|
||||
() => (target ? deleteEventListener(target, type, listener, useCapture) : null),
|
||||
useSafe,
|
||||
)
|
||||
}
|
||||
|
||||
// TODO: full correct semantic
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ export const LogLevel = {
|
|||
Errors: 2,
|
||||
Silent: 0,
|
||||
} as const
|
||||
type LogLevel = typeof LogLevel[keyof typeof LogLevel]
|
||||
type LogLevel = (typeof LogLevel)[keyof typeof LogLevel]
|
||||
|
||||
type CustomLevel = {
|
||||
error: boolean
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { createEventListener, deleteEventListener } from '../utils.js'
|
||||
|
||||
type NodeCallback = (node: Node, isStart: boolean) => void
|
||||
type ElementListener = [string, EventListener, boolean]
|
||||
|
||||
|
|
@ -19,7 +21,7 @@ export default class Nodes {
|
|||
if (id === undefined) {
|
||||
return
|
||||
}
|
||||
node.addEventListener(type, listener, useCapture)
|
||||
createEventListener(node, type, listener, useCapture)
|
||||
let listeners = this.elementListeners.get(id)
|
||||
if (listeners === undefined) {
|
||||
listeners = []
|
||||
|
|
@ -49,7 +51,7 @@ export default class Nodes {
|
|||
if (listeners !== undefined) {
|
||||
this.elementListeners.delete(id)
|
||||
listeners.forEach((listener) =>
|
||||
node.removeEventListener(listener[0], listener[1], listener[2]),
|
||||
deleteEventListener(node, listener[0], listener[1], listener[2]),
|
||||
)
|
||||
}
|
||||
this.totalNodeAmount--
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { createMutationObserver, ngSafeBrowserMethod } from '../../utils.js'
|
||||
import {
|
||||
RemoveNodeAttribute,
|
||||
SetNodeAttributeURLBased,
|
||||
|
|
@ -66,8 +67,11 @@ export default abstract class Observer {
|
|||
private readonly indexes: Array<number> = []
|
||||
private readonly attributesMap: Map<number, Set<string>> = new Map()
|
||||
private readonly textSet: Set<number> = new Set()
|
||||
constructor(protected readonly app: App, protected readonly isTopContext = false) {
|
||||
this.observer = new MutationObserver(
|
||||
constructor(
|
||||
protected readonly app: App,
|
||||
protected readonly isTopContext = false,
|
||||
) {
|
||||
this.observer = createMutationObserver(
|
||||
this.app.safe((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
// mutations order is sequential
|
||||
|
|
@ -114,7 +118,7 @@ export default abstract class Observer {
|
|||
}
|
||||
}
|
||||
this.commitNodes()
|
||||
}),
|
||||
}) as MutationCallback,
|
||||
)
|
||||
}
|
||||
private clear(): void {
|
||||
|
|
|
|||
|
|
@ -24,7 +24,10 @@ export default class Sanitizer {
|
|||
private readonly hidden: Set<number> = new Set()
|
||||
private readonly options: Options
|
||||
|
||||
constructor(private readonly app: App, options: Partial<Options>) {
|
||||
constructor(
|
||||
private readonly app: App,
|
||||
options: Partial<Options>,
|
||||
) {
|
||||
this.options = Object.assign(
|
||||
{
|
||||
obscureTextEmails: true,
|
||||
|
|
|
|||
|
|
@ -35,7 +35,10 @@ export default class Session {
|
|||
private tabId: string
|
||||
public userInfo: UserInfo
|
||||
|
||||
constructor(private readonly app: App, private readonly options: Options) {
|
||||
constructor(
|
||||
private readonly app: App,
|
||||
private readonly options: Options,
|
||||
) {
|
||||
this.createTabId()
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -18,7 +18,10 @@ export class StringDictionary {
|
|||
export default class AttributeSender {
|
||||
private dict = new StringDictionary()
|
||||
|
||||
constructor(private readonly app: App, private readonly isDictDisabled: boolean) {}
|
||||
constructor(
|
||||
private readonly app: App,
|
||||
private readonly isDictDisabled: boolean,
|
||||
) {}
|
||||
|
||||
public sendSetAttribute(id: number, name: string, value: string) {
|
||||
if (this.isDictDisabled) {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import type App from '../app/index.js'
|
||||
import { isURL, IS_FIREFOX, MAX_STR_LEN } from '../utils.js'
|
||||
import { isURL, IS_FIREFOX, MAX_STR_LEN, createMutationObserver } from '../utils.js'
|
||||
import { ResourceTiming, SetNodeAttributeURLBased } from '../app/messages.gen.js'
|
||||
import { hasTag } from '../app/guards.js'
|
||||
|
||||
|
|
@ -81,24 +81,25 @@ export default function (app: App): void {
|
|||
sendSrcset(id, img)
|
||||
}
|
||||
})
|
||||
|
||||
const observer = new MutationObserver((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type === 'attributes') {
|
||||
const target = mutation.target as HTMLImageElement
|
||||
const id = app.nodes.getID(target)
|
||||
if (id === undefined) {
|
||||
return
|
||||
}
|
||||
if (mutation.attributeName === 'src') {
|
||||
sendSrc(id, target)
|
||||
}
|
||||
if (mutation.attributeName === 'srcset') {
|
||||
sendSrcset(id, target)
|
||||
const observer = createMutationObserver(
|
||||
app.safe((mutations) => {
|
||||
for (const mutation of mutations) {
|
||||
if (mutation.type === 'attributes') {
|
||||
const target = mutation.target as HTMLImageElement
|
||||
const id = app.nodes.getID(target)
|
||||
if (id === undefined) {
|
||||
return
|
||||
}
|
||||
if (mutation.attributeName === 'src') {
|
||||
sendSrc(id, target)
|
||||
}
|
||||
if (mutation.attributeName === 'srcset') {
|
||||
sendSrcset(id, target)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
}) as MutationCallback,
|
||||
)
|
||||
|
||||
app.attachStopCallback(() => {
|
||||
observer.disconnect()
|
||||
|
|
|
|||
|
|
@ -113,3 +113,67 @@ export function inIframe() {
|
|||
return true
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Because angular devs decided that its a good idea to override a browser apis
|
||||
* we need to use this to achieve safe behavior
|
||||
* */
|
||||
export function ngSafeBrowserMethod(method: string): string {
|
||||
// @ts-ignore
|
||||
return window.Zone && '__symbol__' in window.Zone
|
||||
? // @ts-ignore
|
||||
window['Zone']['__symbol__'](method)
|
||||
: method
|
||||
}
|
||||
|
||||
export function createMutationObserver(cb: MutationCallback) {
|
||||
const mObserver = ngSafeBrowserMethod('MutationObserver') as 'MutationObserver'
|
||||
return new window[mObserver](cb)
|
||||
}
|
||||
|
||||
export function createEventListener(
|
||||
target: EventTarget,
|
||||
event: string,
|
||||
cb: EventListenerOrEventListenerObject,
|
||||
capture?: boolean,
|
||||
) {
|
||||
const safeAddEventListener = ngSafeBrowserMethod('addEventListener') as 'addEventListener'
|
||||
target[safeAddEventListener](event, cb, capture)
|
||||
}
|
||||
|
||||
export function deleteEventListener(
|
||||
target: EventTarget,
|
||||
event: string,
|
||||
cb: EventListenerOrEventListenerObject,
|
||||
capture?: boolean,
|
||||
) {
|
||||
const safeRemoveEventListener = ngSafeBrowserMethod(
|
||||
'removeEventListener',
|
||||
) as 'removeEventListener'
|
||||
target[safeRemoveEventListener](event, cb, capture)
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a brief polyfill that suits our needs
|
||||
* I took inspiration from Microsoft Clarity polyfill on this one
|
||||
* then adapted it a little bit
|
||||
*
|
||||
* I'm very grateful for their bright idea
|
||||
* */
|
||||
export function requestIdleCb(callback: () => void) {
|
||||
const taskTimeout = 3000
|
||||
if (window.requestIdleCallback) {
|
||||
return window.requestIdleCallback(callback, { timeout: taskTimeout })
|
||||
} else {
|
||||
const channel = new MessageChannel()
|
||||
const incoming = channel.port1
|
||||
const outgoing = channel.port2
|
||||
|
||||
incoming.onmessage = (): void => {
|
||||
callback()
|
||||
}
|
||||
requestAnimationFrame((): void => {
|
||||
outgoing.postMessage(1)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,8 @@ import {
|
|||
hasOpenreplayAttribute,
|
||||
canAccessIframe,
|
||||
generateRandomId,
|
||||
ngSafeBrowserMethod,
|
||||
requestIdleCb,
|
||||
} from '../main/utils.js'
|
||||
|
||||
describe('adjustTimeOrigin', () => {
|
||||
|
|
@ -184,3 +186,59 @@ describe('generateRandomId', () => {
|
|||
expect(/^[0-9a-f]+$/.test(id)).toBe(true)
|
||||
})
|
||||
})
|
||||
|
||||
describe('ngSafeBrowserMethod', () => {
|
||||
test('returns the method as-is if Zone and __symbol__ are not in window.Zone', () => {
|
||||
//@ts-ignore
|
||||
window.Zone = undefined // Ensure Zone is not in the window object
|
||||
expect(ngSafeBrowserMethod('someMethod')).toBe('someMethod')
|
||||
})
|
||||
|
||||
test('returns the __symbol__ of the method if Zone and __symbol__ are in window.Zone', () => {
|
||||
//@ts-ignore
|
||||
window.Zone = {
|
||||
__symbol__: (method: string) => `__${method}__`,
|
||||
}
|
||||
expect(ngSafeBrowserMethod('someMethod')).toBe('__someMethod__')
|
||||
})
|
||||
})
|
||||
|
||||
describe('requestIdleCb', () => {
|
||||
test('uses window.requestIdleCallback when available', () => {
|
||||
const callback = jest.fn()
|
||||
// @ts-ignore
|
||||
window.requestIdleCallback = callback
|
||||
|
||||
requestIdleCb(callback)
|
||||
|
||||
expect(callback).toBeCalled()
|
||||
})
|
||||
|
||||
test('falls back to using a MessageChannel if requestIdleCallback is not available', () => {
|
||||
const callback = jest.fn()
|
||||
class MessageChannelMock {
|
||||
port1 = {
|
||||
// @ts-ignore
|
||||
postMessage: (v: any) => this.port2.onmessage(v),
|
||||
onmessage: null,
|
||||
}
|
||||
port2 = {
|
||||
onmessage: null,
|
||||
// @ts-ignore
|
||||
postMessage: (v: any) => this.port1.onmessage(v),
|
||||
}
|
||||
}
|
||||
// @ts-ignore
|
||||
globalThis.MessageChannel = MessageChannelMock
|
||||
// @ts-ignore
|
||||
globalThis.requestAnimationFrame = (cb: () => void) => cb()
|
||||
// @ts-ignore
|
||||
window.requestIdleCallback = undefined
|
||||
|
||||
requestIdleCb(callback)
|
||||
|
||||
// You can assert that the callback was called using the MessageChannel approach.
|
||||
// This is more challenging to test, so it's recommended to mock MessageChannel.
|
||||
expect(callback).toBeCalled()
|
||||
})
|
||||
})
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue