diff --git a/.harness/orgs/PROD/projects/Harness_Split/pipelines/javascript_browser_client_ci.yaml b/.harness/orgs/PROD/projects/Harness_Split/pipelines/javascript_browser_client_ci.yaml index 9791462..3bd06fb 100644 --- a/.harness/orgs/PROD/projects/Harness_Split/pipelines/javascript_browser_client_ci.yaml +++ b/.harness/orgs/PROD/projects/Harness_Split/pipelines/javascript_browser_client_ci.yaml @@ -3,20 +3,17 @@ pipeline: identifier: javascript_browser_client_ci projectIdentifier: Harness_Split orgIdentifier: PROD - tags: - fme-sdk: "" - team: SDK + tags: {} properties: ci: codebase: connectorRef: fmegithubharnessgitops repoName: javascript-browser-client build: <+input> - depth: 0 stages: - stage: - name: Build and Test - identifier: Build_and_Test + name: Check-Test-Build-Upload + identifier: Check_Test_Build_Upload description: "" type: CI spec: @@ -24,281 +21,107 @@ pipeline: caching: enabled: true override: true - platform: - os: Linux - arch: Amd64 - runtime: - type: Cloud - spec: - size: flex + paths: [] + buildIntelligence: + enabled: false execution: steps: - step: type: Run - name: Install Node - identifier: Install_Node - spec: - shell: Bash - command: |- - curl https://mise.run | sh - export PATH="$HOME/.local/bin:$PATH" - mise use --global node@lts - node --version - npm --version - - step: - type: Run - name: Install Chrome - identifier: Install_Chrome - spec: - shell: Bash - # puppeteer e2e tests require a real Chrome binary; version pinned to match GHA (125) - command: |- - export PUPPETEER_SKIP_DOWNLOAD=true - curl -fsSL https://dl.google.com/linux/direct/google-chrome-stable_current_amd64.deb -o /tmp/chrome.deb - apt-get update -qq && apt-get install -y -qq /tmp/chrome.deb || true - # Fallback: install via chromium if exact version not available - which google-chrome-stable || apt-get install -y -qq chromium-browser - CHROME_BIN=$(which google-chrome-stable || which chromium-browser || which chromium) - echo "CHROME_BIN=$CHROME_BIN" - export CHROME_BIN - - step: - type: Run - name: Install Dependencies - identifier: Install_Dependencies - spec: - shell: Bash - command: |- - export PATH="$HOME/.local/bin:$PATH" - eval "$(mise activate bash)" - export PUPPETEER_SKIP_DOWNLOAD=true - npm ci - - step: - type: Run - name: Check TypeScript Declarations - identifier: Check_TypeScript_Declarations - spec: - shell: Bash - command: |- - export PATH="$HOME/.local/bin:$PATH" - eval "$(mise activate bash)" - npm run test-ts-decls - - step: - type: Run - name: Check Lint and Types - identifier: Check_Lint_and_Types - spec: - shell: Bash - command: |- - export PATH="$HOME/.local/bin:$PATH" - eval "$(mise activate bash)" - npm run check - - step: - type: Run - name: Run Tests - identifier: Run_Tests - spec: - shell: Bash - command: |- - export PATH="$HOME/.local/bin:$PATH" - eval "$(mise activate bash)" - CHROME_BIN=$(which google-chrome-stable || which chromium-browser || which chromium) - export CHROME_BIN - export PUPPETEER_SKIP_DOWNLOAD=true - npm run test - - step: - type: Run - name: Build - identifier: Build - spec: - shell: Bash - command: |- - export PATH="$HOME/.local/bin:$PATH" - eval "$(mise activate bash)" - BUILD_BRANCH=<+codebase.branch> npm run build - - step: - type: Run - name: SonarQube Scan - identifier: SonarQube_Scan - when: - stageStatus: Success - spec: - shell: Sh - command: |- - export SONAR_SCANNER_VERSION=5.0.1.3006 - curl -sSLo sonar-scanner.zip \ - "https://binaries.sonarsource.com/Distribution/sonar-scanner-cli/sonar-scanner-cli-${SONAR_SCANNER_VERSION}-linux.zip" - unzip -q sonar-scanner.zip - export PATH="$PWD/sonar-scanner-${SONAR_SCANNER_VERSION}-linux/bin:$PATH" - apt-get install -y openjdk-17-jdk -qq - - VERSION=$(node -e "console.log(require('./package.json').version)") - - if [ "<+codebase.build.type>" = "PR" ]; then - sonar-scanner \ - -Dsonar.projectKey=javascript-browser-client \ - -Dsonar.projectName=javascript-browser-client \ - -Dsonar.sources=src \ - -Dsonar.host.url=https://sonar.harness.io \ - -Dsonar.token=<+secrets.getValue("sonarqube-token")> \ - -Dsonar.exclusions="**/node_modules/**,**/umd/**,**/cjs/**,**/esm/**" \ - -Dsonar.projectVersion="${VERSION}" \ - -Dsonar.pullrequest.key=<+codebase.prNumber> \ - -Dsonar.pullrequest.branch=<+codebase.branch> \ - -Dsonar.pullrequest.base=<+codebase.targetBranch> - else - sonar-scanner \ - -Dsonar.projectKey=javascript-browser-client \ - -Dsonar.projectName=javascript-browser-client \ - -Dsonar.sources=src \ - -Dsonar.host.url=https://sonar.harness.io \ - -Dsonar.token=<+secrets.getValue("sonarqube-token")> \ - -Dsonar.exclusions="**/node_modules/**,**/umd/**,**/cjs/**,**/esm/**" \ - -Dsonar.projectVersion="${VERSION}" \ - -Dsonar.branch.name=<+codebase.branch> - fi - - step: - type: Run - name: Post Quality Gate - identifier: Post_Quality_Gate - when: - stageStatus: Success + name: npm ci + identifier: npm_ci spec: + connectorRef: dockerhub + image: node:lts shell: Bash - command: |- - #!/bin/bash - set -e - - SONAR_TOKEN="<+secrets.getValue("sonarqube-token")>" - SONAR_URL="https://sonar.harness.io" - SONAR_PROJECT_KEY="javascript-browser-client" - GITHUB_TOKEN="<+secrets.getValue("github-devops-token")>" - GITHUB_REPO="javascript-browser-client" - COMMIT_SHA="<+codebase.commitSha>" - - STATUS_JSON=$(curl -sf \ - -H "Authorization: Bearer ${SONAR_TOKEN}" \ - "${SONAR_URL}/api/qualitygates/project_status?projectKey=${SONAR_PROJECT_KEY}") - - QG_STATUS=$(echo "$STATUS_JSON" | python3 -c "import sys,json; print(json.load(sys.stdin)['projectStatus']['status'])") - - case "$QG_STATUS" in - OK) GH_STATE="success"; DESCRIPTION="Quality gate passed" ;; - ERROR) GH_STATE="failure"; DESCRIPTION="Quality gate failed" ;; - WARN) GH_STATE="success"; DESCRIPTION="Quality gate passed with warnings" ;; - *) GH_STATE="pending"; DESCRIPTION="Quality gate status unknown" ;; - esac - - TARGET_URL="${SONAR_URL}/dashboard?id=${SONAR_PROJECT_KEY}" - - curl -sf -X POST \ - -H "Authorization: token ${GITHUB_TOKEN}" \ - -H "Accept: application/vnd.github.v3+json" \ - -H "Content-Type: application/json" \ - -d "{\"state\":\"${GH_STATE}\",\"description\":\"${DESCRIPTION}\",\"context\":\"sonarqube/quality-gate\",\"target_url\":\"${TARGET_URL}\"}" \ - "https://api.github.com/repos/splitio/${GITHUB_REPO}/statuses/${COMMIT_SHA}" - - echo "Posted SonarQube quality gate status: ${GH_STATE}" - - stage: - name: Deploy to S3 Stage - identifier: Deploy_to_S3_Stage - type: CI - spec: - cloneCodebase: true - buildIntelligence: - enabled: false - execution: - steps: + command: npm ci + envVariables: + PUPPETEER_SKIP_DOWNLOAD: "true" - step: type: Run - name: Build UMD Assets - identifier: Build_UMD_Assets + name: npm run test-ts-decls + identifier: npm_run_test_ts_decls spec: connectorRef: dockerhub image: node:lts shell: Bash - command: |- - export PUPPETEER_SKIP_DOWNLOAD=true - npm ci - BUILD_BRANCH=<+codebase.branch> npm run build:umd + command: npm run test-ts-decls + resources: + limits: + memory: 2Gi + cpu: "1" - step: type: Run - name: Deploy to S3 Stage - identifier: Deploy_to_S3_Stage + name: npm run check + identifier: npm_run_check spec: connectorRef: dockerhub - image: amazon/aws-cli:2.31.5 + image: node:lts shell: Bash - command: aws s3 sync $SOURCE_DIR s3://$BUCKET/$DEST_DIR $ARGS - envVariables: - BUCKET: split-public-stage - SOURCE_DIR: ./umd - DEST_DIR: sdk - ARGS: --acl public-read --follow-symlinks --cache-control max-age=31536000,public - AWS_DEFAULT_REGION: us-east-1 - infrastructure: - type: KubernetesDirect - spec: - connectorRef: use1stage1cd - namespace: harness-delegate - # VERIFY: service account needs IRSA binding to the equivalent of arn:aws:iam::079419646996:role/gha-public-assets-role - serviceAccountName: use1-stage-1-javascript-browser-client-s3 - automountServiceAccountToken: false - nodeSelector: {} - os: Linux - delegateSelectors: - - use1-stage-1-cd - when: - pipelineStatus: Success - condition: <+trigger.event> == "PUSH" && <+codebase.branch> == "development" - - stage: - name: Deploy to S3 Prod - identifier: Deploy_to_S3_Prod - type: CI - spec: - cloneCodebase: true - buildIntelligence: - enabled: false - execution: - steps: + command: npm run check - step: type: Run - name: Build UMD Assets - identifier: Build_UMD_Assets + name: npm run test + identifier: npm_run_test spec: connectorRef: dockerhub image: node:lts shell: Bash command: |- - export PUPPETEER_SKIP_DOWNLOAD=true - npm ci - BUILD_BRANCH=<+codebase.branch> npm run build:umd + apt-get update -qq && apt-get install -y -qq chromium + export CHROME_BIN=$(command -v chromium) + "$CHROME_BIN" --version + npm run test + resources: + limits: + memory: 8Gi + cpu: "4" - step: type: Run - name: Deploy to S3 Prod - identifier: Deploy_to_S3_Prod + name: npm run build + identifier: npm_run_build spec: connectorRef: dockerhub - image: amazon/aws-cli:2.31.5 + image: node:lts shell: Bash - command: aws s3 sync $SOURCE_DIR s3://$BUCKET/$DEST_DIR $ARGS - envVariables: - BUCKET: split-public - SOURCE_DIR: ./umd - DEST_DIR: sdk - ARGS: --acl public-read --follow-symlinks --cache-control max-age=31536000,public - AWS_DEFAULT_REGION: us-east-1 + command: BUILD_BRANCH=<+codebase.branch> npm run build + - parallel: + - step: + type: Run + name: upload dev assets to CDN + identifier: upload_dev_assets_to_CDN + spec: + connectorRef: dockerhub + image: amazon/aws-cli:2.31.5 + shell: Bash + command: aws s3 sync ./umd s3://split-public-stage/sdk --acl public-read --follow-symlinks --cache-control max-age=31536000,public + envVariables: + AWS_DEFAULT_REGION: us-east-1 + when: + stageStatus: Success + condition: <+trigger.event> == "PUSH" && <+trigger.branch> == "development" + - step: + type: Run + name: upload prod assets to CDN + identifier: upload_prod_assets_to_CDN + spec: + connectorRef: dockerhub + image: amazon/aws-cli:2.31.5 + shell: Bash + command: aws s3 sync ./umd s3://split-public/sdk --acl public-read --follow-symlinks --cache-control max-age=31536000,public + envVariables: + AWS_DEFAULT_REGION: us-east-1 + when: + stageStatus: Success + condition: <+trigger.event> == "PUSH" && <+trigger.branch> == "main" infrastructure: type: KubernetesDirect spec: - connectorRef: use1prod1cd + connectorRef: "<+codebase.branch == \"main\" ? \"use1prod1cd\" : \"use1stage1cd\">" namespace: harness-delegate - # VERIFY: service account needs IRSA binding to the equivalent of arn:aws:iam::825951051969:role/gha-public-assets-role - serviceAccountName: use1-prod-1-javascript-browser-client-s3 + serviceAccountName: "<+codebase.branch == \"main\" ? \"use1-prod-1-public-assets\" : \"use1-stage-1-public-assets\">" automountServiceAccountToken: false nodeSelector: {} os: Linux delegateSelectors: - - use1-prod-1-cd - when: - pipelineStatus: Success - condition: <+trigger.event> == "PUSH" && <+codebase.branch> == "main" + - "<+codebase.branch == \"main\" ? \"use1-prod-1-cd\" : \"use1-stage-1-cd\">" diff --git a/package-lock.json b/package-lock.json index 2802921..f1d93c4 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "1.7.1", + "version": "1.7.1-rc.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@splitsoftware/splitio-browserjs", - "version": "1.7.1", + "version": "1.7.1-rc.1", "license": "Apache-2.0", "dependencies": { "@splitsoftware/splitio-commons": "2.12.1", @@ -617,9 +617,9 @@ } }, "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz", + "integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==", "dev": true, "license": "MIT", "dependencies": { @@ -2186,9 +2186,9 @@ } }, "node_modules/brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "license": "MIT", "dependencies": { @@ -3921,9 +3921,9 @@ "dev": true }, "node_modules/glob/node_modules/brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "dev": true, "license": "MIT", "dependencies": { @@ -5422,9 +5422,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, "funding": [ { @@ -8930,9 +8930,9 @@ } }, "js-yaml": { - "version": "3.14.2", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz", - "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==", + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz", + "integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==", "dev": true, "requires": { "argparse": "^1.0.7", @@ -10107,9 +10107,9 @@ } }, "brace-expansion": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.15.tgz", - "integrity": "sha512-EwOCDEex4quD37XhqM3omwtMoJjr//isUZz1JopUNWms+4Z2ViyM/k1YIRePpoVNnQhENnxtFjLaxNHrT7xIUg==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", + "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", "dev": true, "requires": { "balanced-match": "^1.0.0", @@ -11364,9 +11364,9 @@ }, "dependencies": { "brace-expansion": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.1.tgz", - "integrity": "sha512-WR1cURNjuvBLMZBMbqM0UoE+WAfdUcEV1ccD8PVBVOI+Z3ND4+SZbN8RsfT2bMuG1qwz5RFvPukSZm5fF2D5eA==", + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", + "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", "dev": true, "requires": { "balanced-match": "^1.0.0" @@ -12481,9 +12481,9 @@ "dev": true }, "js-yaml": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.2.0.tgz", - "integrity": "sha512-ePWsvanv0DWuDRsW8dnt+R4jQ31SCRCQ7hhNcPXZPsoBZiemuZNYGf7adZdqX2D86j6rvKp3RpCxVTSb8WQlOw==", + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", + "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", "dev": true, "requires": { "argparse": "^2.0.1" diff --git a/package.json b/package.json index c27ff75..3c7d291 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@splitsoftware/splitio-browserjs", - "version": "1.7.1", + "version": "1.7.1-rc.1", "description": "Split SDK for JavaScript on Browser", "main": "cjs/index.js", "module": "esm/index.js", diff --git a/src/__tests__/offline/browser.spec.js b/src/__tests__/offline/browser.spec.js index f0f6b3f..f9213ce 100644 --- a/src/__tests__/offline/browser.spec.js +++ b/src/__tests__/offline/browser.spec.js @@ -24,6 +24,19 @@ const replySpy = spy => { return 200; }; +// polls `condition` until it's true or `timeout` ms elapse, instead of a fixed wait, to avoid flakiness under CI load +const waitUntil = (condition, timeout = 10000, interval = 1000) => { + const start = Date.now(); + return new Promise((resolve, reject) => { + const check = () => { + if (condition()) return resolve(); + if (Date.now() - start >= timeout) return reject(new Error('waitUntil timed out')); + setTimeout(check, interval); + }; + check(); + }); +}; + const configMocks = () => { fetchMock.mock(new RegExp(`${url(settings, '/splitChanges/')}.*`), () => replySpy(spySplitChanges)); fetchMock.mock(new RegExp(`${url(settings, '/segmentChanges/')}.*`), () => replySpy(spySegmentChanges)); @@ -255,7 +268,7 @@ tape('Browser offline mode', function (assert) { setTimeout(() => { factory.settings.features = { testing_split: 'on', testing_split_with_config: { treatment: 'off', config: '{ "color": "blue" }' } }; }, 750); // once updated, test again. - client.once(client.Event.SDK_UPDATE, function (metadata) { + client.once(client.Event.SDK_UPDATE, async (metadata) => { assert.true((Date.now() - readyTimestamp) > 1000, 'Should only emit SDK_UPDATE after a real update.'); assert.true(metadata != null && typeof metadata.type === 'string' && ['FLAGS_UPDATE', 'SEGMENTS_UPDATE'].includes(metadata.type), 'SDK_UPDATE must receive SdkUpdateMetadata with type'); assert.true(Array.isArray(metadata.names), 'SDK_UPDATE must receive SdkUpdateMetadata with names array'); @@ -334,38 +347,42 @@ tape('Browser offline mode', function (assert) { testing_not_exist: { treatment: 'control', config: null } }); - // timeout to wait SDK_UPDATE on all factories - setTimeout(() => { - const destroyPromises = [ - sharedClient.destroy(), client.destroy(), - ...factories.map(f => f.client().destroy()) - ]; - - // When both promises have been resolved, we check for network activity - Promise.all(destroyPromises).then(() => { - // We test the breakdown instead of just the misc because it's faster to spot where the issue is - assert.notOk(spySplitChanges.called, 'On offline mode we should not call the splitChanges endpoint.'); - assert.notOk(spySegmentChanges.called, 'On offline mode we should not call the segmentChanges endpoint.'); - assert.notOk(spyMemberships.called, 'On offline mode we should not call the memberships endpoint.'); - assert.notOk(spyEventsBulk.called, 'On offline mode we should not call the events endpoint.'); - assert.notOk(spyTestImpressionsBulk.called, 'On offline mode we should not call the impressions endpoint.'); - assert.notOk(spyTestImpressionsCount.called, 'On offline mode we should not call the impressions count endpoint.'); - assert.notOk(spyMetricsTimes.called, 'On offline mode we should not call the metric times endpoint.'); - assert.notOk(spyMetricsCounters.called, 'On offline mode we should not call the metric counters endpoint.'); - assert.notOk(spyAny.called, 'On offline mode we should NOT call to ANY endpoint, we are completely isolated from BE.'); - - // SDK events on shared client - assert.equal(sharedReadyCount, 1, 'Shared client should have emitted SDK_READY event once'); - assert.equal(sharedUpdateCount, 1, 'Shared client should have emitted SDK_UPDATE event once'); - - // SDK events on other factory clients - assert.equal(readyCount, factories.length, 'Each factory client should have emitted SDK_READY event once'); - assert.equal(updateCount, factories.length - 1, 'Each factory client except one should have emitted SDK_UPDATE event once'); - assert.equal(readyFromCacheCount, 2, 'The main and shared client of the factory with LOCALSTORAGE should have emitted SDK_READY_FROM_CACHE event'); - - assert.end(); - }); - }); - }, 3500); + // wait for SDK_UPDATE on all factories + try { + await waitUntil(() => updateCount === factories.length - 1); + } catch (err) { + assert.fail(err.message); + assert.end(); + } + + const destroyPromises = [ + sharedClient.destroy(), client.destroy(), + ...factories.map(f => f.client().destroy()) + ]; + + // When both promises have been resolved, we check for network activity + await Promise.all(destroyPromises); + // We test the breakdown instead of just the misc because it's faster to spot where the issue is + assert.notOk(spySplitChanges.called, 'On offline mode we should not call the splitChanges endpoint.'); + assert.notOk(spySegmentChanges.called, 'On offline mode we should not call the segmentChanges endpoint.'); + assert.notOk(spyMemberships.called, 'On offline mode we should not call the memberships endpoint.'); + assert.notOk(spyEventsBulk.called, 'On offline mode we should not call the events endpoint.'); + assert.notOk(spyTestImpressionsBulk.called, 'On offline mode we should not call the impressions endpoint.'); + assert.notOk(spyTestImpressionsCount.called, 'On offline mode we should not call the impressions count endpoint.'); + assert.notOk(spyMetricsTimes.called, 'On offline mode we should not call the metric times endpoint.'); + assert.notOk(spyMetricsCounters.called, 'On offline mode we should not call the metric counters endpoint.'); + assert.notOk(spyAny.called, 'On offline mode we should NOT call to ANY endpoint, we are completely isolated from BE.'); + + // SDK events on shared client + assert.equal(sharedReadyCount, 1, 'Shared client should have emitted SDK_READY event once'); + assert.equal(sharedUpdateCount, 1, 'Shared client should have emitted SDK_UPDATE event once'); + + // SDK events on other factory clients + assert.equal(readyCount, factories.length, 'Each factory client should have emitted SDK_READY event once'); + assert.equal(updateCount, factories.length - 1, 'Each factory client except one should have emitted SDK_UPDATE event once'); + assert.equal(readyFromCacheCount, 2, 'The main and shared client of the factory with LOCALSTORAGE should have emitted SDK_READY_FROM_CACHE event'); + + assert.end(); + }); }); }); diff --git a/src/settings/defaults.ts b/src/settings/defaults.ts index d8ae1f1..eff20be 100644 --- a/src/settings/defaults.ts +++ b/src/settings/defaults.ts @@ -2,7 +2,7 @@ import type SplitIO from '@splitsoftware/splitio-commons/types/splitio'; import { LogLevels, isLogLevelString } from '@splitsoftware/splitio-commons/src/logger/index'; import { CONSENT_GRANTED } from '@splitsoftware/splitio-commons/src/utils/constants'; -const packageVersion = '1.7.1'; +const packageVersion = '1.7.1-rc.1'; /** * In browser, the default debug level, can be set via the `localStorage.splitio_debug` item.