From f73597d7d19ecd000e46723906c0757796fa52f5 Mon Sep 17 00:00:00 2001 From: Wyatt Johnson Date: Wed, 13 May 2020 16:47:45 +0000 Subject: [PATCH] [CORL-1013] Count Reset (#2960) * feat: added reset option for count.js * fix: adjust reset beheviour * fix: switched to bundlesize2 * fix: added flag to enable github checks Co-authored-by: Vinh --- .circleci/config.yml | 16 +- package.json | 4 + src/core/client/count/index.ts | 56 ++++- src/core/client/count/injectJSONPCallback.ts | 5 +- .../test/__snapshots__/basic.spec.ts.snap | 200 +++++++++++++++++- src/core/client/count/test/basic.spec.ts | 36 +++- src/core/client/framework/utils/jsonp.ts | 32 +-- .../server/app/handlers/api/story/count.ts | 92 ++++---- 8 files changed, 356 insertions(+), 85 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index eb7babba3..df0979e35 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -1,8 +1,8 @@ # job_environment will setup the environment for any job being executed. job_environment: &job_environment - NODE_ENV: test - WEBPACK_MAX_CORES: 4 - NODE_OPTIONS: --max-old-space-size=8192 + NODE_ENV: "test" + WEBPACK_MAX_CORES: "4" + NODE_OPTIONS: "--max-old-space-size=8192" # job_defaults applies all the defaults for each job. job_defaults: &job_defaults @@ -49,7 +49,8 @@ jobs: - ~/.npm - persist_to_workspace: root: . - paths: node_modules + paths: + - node_modules # lint will perform file linting. lint: @@ -78,7 +79,7 @@ jobs: <<: *job_defaults environment: <<: *job_environment - CI: true + CI: "true" JEST_JUNIT_OUTPUT: "reports/junit/js-test-results.xml" steps: - checkout @@ -115,14 +116,15 @@ jobs: no_output_timeout: 30m - run: name: Verify Bundle Size - command: npx bundlesize + command: npx bundlesize2 --enable-github-checks - save_cache: key: v1-build-cache-{{ .Branch }}-{{ .Revision }} paths: - ./dist - persist_to_workspace: root: . - paths: dist + paths: + - dist # docker_tests will test that the docker build process completes. docker_tests: diff --git a/package.json b/package.json index c21f8d350..59225f4a2 100644 --- a/package.json +++ b/package.json @@ -420,6 +420,10 @@ { "path": "./dist/static/assets/js/embed.js", "maxSize": "15 kB" + }, + { + "path": "./dist/static/assets/js/count.js", + "maxSize": "2 kB" } ], "graphql-schema-linter": { diff --git a/src/core/client/count/index.ts b/src/core/client/count/index.ts index e1b6ba00e..ef7cefae0 100644 --- a/src/core/client/count/index.ts +++ b/src/core/client/count/index.ts @@ -10,49 +10,89 @@ import injectJSONPCallback from "./injectJSONPCallback"; interface CountQueryArgs { id?: string; url?: string; - notext?: boolean; + notext: boolean; } /** createCountQueryRef creates a unique reference from the query args */ function createCountQueryRef(args: CountQueryArgs) { - return btoa(`${JSON.stringify(!!args.notext)};${args.id || args.url}`); + return btoa(`${args.notext ? "true" : "false"};${args.id || args.url}`); +} + +interface DetectAndInjectArgs { + reset?: boolean; } /** Detects count elements and use jsonp to inject the counts. */ -function detectAndInject() { +function detectAndInject(opts: DetectAndInjectArgs = {}) { const ORIGIN = getCurrentScriptOrigin(ORIGIN_FALLBACK_ID); const STORY_URL = resolveStoryURL(); + /** A map of references pointing to the count query arguments */ const queryMap: Record = {}; // Find all the selected elements and fill the queryMap. const elements = document.querySelectorAll(COUNT_SELECTOR); Array.prototype.forEach.call(elements, (element: HTMLElement) => { - let url = element.dataset.coralUrl; const id = element.dataset.coralId; const notext = element.dataset.coralNotext === "true"; + + // If there is no URL or ID on the element, add one based on the story url + // that we detected. + let url = element.dataset.coralUrl; if (!url && !id) { url = STORY_URL; element.dataset.coralUrl = STORY_URL; } + + // Construct the args for generating the ref. const args = { id, url, notext }; - const ref = createCountQueryRef(args); + + // Get or create a ref. + let ref = element.dataset.coralRef; + if (!ref) { + ref = createCountQueryRef(args); + element.dataset.coralRef = ref; + } else { + // The element already had a ref attached to it, which means it's already + // been processed. If we aren't resetting, we should skip this. + if (!opts.reset) { + return; + } + } + + // Add it to the managed set if we haven't already. if (!(ref in queryMap)) { queryMap[ref] = args; } - element.dataset.coralRef = ref; }); // Call server using JSONP. Object.keys(queryMap).forEach((ref) => { const { url, id, notext } = queryMap[ref]; - const args = { url, id, notext: notext ? "true" : "false", ref }; + + // Compile the arguments used to generate the + const args: Record = { + url, + id, + notext: notext ? "true" : "false", + ref, + }; + + // Special handling for when the count is reset. + if (opts.reset) { + // Add the date as an argument to cache bust. + args.d = Date.now().toString(); + } + + // Add the script element with the specified options to the page. jsonp(`${ORIGIN}/api/story/count.js`, "CoralCount.setCount", args); }); } export function main() { - injectJSONPCallback(); + // Inject the JSONP callback with the detection script to be used as the + // CoralCount.getCount callback. + injectJSONPCallback(detectAndInject); detectAndInject(); } diff --git a/src/core/client/count/injectJSONPCallback.ts b/src/core/client/count/injectJSONPCallback.ts index 11b2648f7..a961b92fb 100644 --- a/src/core/client/count/injectJSONPCallback.ts +++ b/src/core/client/count/injectJSONPCallback.ts @@ -1,7 +1,9 @@ import { COUNT_SELECTOR } from "coral-framework/constants"; +type GetCountFunction = (opts?: { reset?: boolean }) => void; + /** Injects a global CoralCount callback into the window object to be used in JSONP */ -function injectJSONPCallback() { +function injectJSONPCallback(getCount: GetCountFunction) { (window as any).CoralCount = { setCount: (data: { ref: string; html: string }) => { // Find all the elements with ref. @@ -12,6 +14,7 @@ function injectJSONPCallback() { element.innerHTML = data.html; }); }, + getCount, }; } diff --git a/src/core/client/count/test/__snapshots__/basic.spec.ts.snap b/src/core/client/count/test/__snapshots__/basic.spec.ts.snap index 1329505bc..a1c91425f 100644 --- a/src/core/client/count/test/__snapshots__/basic.spec.ts.snap +++ b/src/core/client/count/test/__snapshots__/basic.spec.ts.snap @@ -24,13 +24,205 @@ exports[`Calls JSONP 1`] = ` data-coral-url="http://localhost:8080/" />