{"id":29776862,"url":"https://github.com/godaddy/timings-client-js","last_synced_at":"2025-07-27T10:20:49.484Z","repository":{"id":25702091,"uuid":"105833487","full_name":"godaddy/timings-client-js","owner":"godaddy","description":null,"archived":false,"fork":false,"pushed_at":"2024-03-15T23:06:11.000Z","size":799,"stargazers_count":1,"open_issues_count":34,"forks_count":1,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-07-18T09:59:29.156Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/godaddy.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2017-10-05T00:27:16.000Z","updated_at":"2023-10-06T10:19:24.000Z","dependencies_parsed_at":"2023-01-14T03:13:23.890Z","dependency_job_id":"d86fdd15-b791-4941-b6a9-d58070bdfafb","html_url":"https://github.com/godaddy/timings-client-js","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/godaddy/timings-client-js","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godaddy%2Ftimings-client-js","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godaddy%2Ftimings-client-js/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godaddy%2Ftimings-client-js/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godaddy%2Ftimings-client-js/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/godaddy","download_url":"https://codeload.github.com/godaddy/timings-client-js/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/godaddy%2Ftimings-client-js/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":266052802,"owners_count":23869489,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-07-27T10:20:45.932Z","updated_at":"2025-07-27T10:20:49.478Z","avatar_url":"https://github.com/godaddy.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# timings-client-js\n\nClient for [Timings API](https://www.github.com/godaddy/timings) to support **JavaScript** based test environments\n\n## NEW FEATURE [MULTI-RUN]\n\nThe client now supports the new `multirun` feature that was introduces in version 1.3.0 of the API. If you want perform multiple runs of the same functional test but only have one of the runs be used for performance assertion, this feature is for you! Simply run your test script in a loop, calling the API during each loop but this time, add the `multirun` key to your POST payload to the `navtiming`, `usertiming` or `apitiming` endpoints. The API will save the performance data and upon the last run, it will pick the 75th percentile result and process that as if it were a normal result. The API will then return the usual response (including the `assert` field!). Hope you like it!\n\n## Purpose\n\n- Sending performance data from functional tests to the [timings API](https://www.github.com/godaddy/timings).\n- This client makes it easy to communicate with the API without the need to setup your own curl/axios/etc. calls.\n- The response contains the necessary fields to validate/assert the performance results (look for the `assert` field!).\n- The API stores the results in ElasticSearch and can be visualized with Kibana.\n- This helps get better visibility into performance improvements/regression trends before moving into production.\n\nTo learn more about ELK (Elastic Search, LogStash, Kibana). Click Here [https://www.elastic.co/products/kibana](https://www.elastic.co/products/kibana)\n\n## Installation\n\nTo use timings-client-js, add it as a 'devDependency' to your project\n\n```shell\nnpm install --save-dev timings-client-js\n```\n\n## Configuration\n\nAdd a custom config file to your project's root folder and edit your default settings. Example:\n\n```javascript\nmodule.exports = {\n    \"PERF_API_URL\": \"http://\u003cAPI host\u003e/v2/api/cicd/\",\n    \"api_timeout\": 2000,\n    \"api_params\": {\n        \"sla\": {\n            \"pageLoadTime\": 2000\n        },\n        \"baseline\": {\n            \"days\": 7,\n            \"perc\": 75,\n            \"padding\": 1.2,\n            \"incl\": {\n                \"env_target\": \"_log_\"\n            }\n        },\n        \"flags\": {\n            \"assertBaseline\": true,\n            \"debug\": false,\n            \"esTrace\": false,\n            \"esCreate\": false,\n            \"passOnFailedAssert\": false\n        },\n        \"log\": {\n            \"test_info\": \"Sample test_info\",\n            \"env_tester\": \"Sample tester\",\n            \"browser\": \"Sample browser\",\n            \"env_target\": \"Sample target\",\n            \"team\": \"SAMPLE TEAM\"\n        }\n    }\n};\n```\n\n## Instrumenting your test scripts\n\nIn your test script(s), you initiate the client with the the `PUtils` class from the `timings-client-js` module. You can pass **just the filename** of your custom config file (file should be in the project root!) to the class. For example:\n\n```javascript\nconst timings = require('timings-client-js');\nconst perf = new timings.PUtils('.perftimings.js');\n```\n\nAlternatively, you can pass an object of the perf timings file contents to declare your perf instantiation.\n```javascript\nconst configFileObj = require('../../.perftimings');\nconst timings = require('timings-client-js');\nconst perf = new timings.PUtils(configFileObj);\n```\n\nWith the client initiated, you can now call the different methods from your script. **NOTE:** the methods are Promise based! Use async methods like `.then((response) =\u003e {})` to capture the responses!\n\n### Example script\n\nBelow is a simple test script to demonstrate the instrumentation:\n\n```javascript\nconst timings = require('timings-client-js');\nconst perf = new timings.PUtils('.perftimings.js');\n\ndescribe('Demo timings-client', function() {\n    it('page performance should be within SLA', function() {\n        const perf_params = perf.getApiParams( {sla:{pageLoadTime: 3000}, debug: true} );\n        return perf.getInjectJS('navtiming', 'visual_complete', true)\n            .then((response) =\u003e {\n                inject_code = response.data.inject_code || '';\n                if (inject_code) {\n                    console.log(\"Encoded INJECT code: \" + JSON.stringify(inject_code, null, 4));\n                    return browser\n                        .url('http://seleniumhq.org/')\n                        .isVisible('#header')\n                        .execute('window.performance.mark(\"visual_complete\");')\n                        .execute(decodeURIComponent(inject_code))\n                        .then((response) =\u003e {\n                            // Grab the browser's response - has the performance data!\n                            const browser_response = response.value || {};\n                            if (browser_response) {\n                                console.log(\"BROWSER response: \" + JSON.stringify(browser_response, null, 4));\n                                return perf.navtiming(browser_response, perf_params, null)\n                                .then((response) =\u003e {\n                                        // Grab the API's response - has the assert field!\n                                        const api_response = response.data || {};\n                                        if (api_response) {\n                                            console.log(\"PERF-API response: \" + JSON.stringify(api_response.export.perf, null, 4));\n                                            expect(api_response.assert, 'Performance failed! assert field is False').to.be.true;\n                                        }\n                                    });\n                            }\n                        })\n                }\n            });\n    });\n});\n```\n\n## Client methods\n\n### `getApiParams({ sla, debug, esTrace, esCreate, days, perc, padding, searchUrl, log })`\n\nCollect or overwrite the default parameters (see above) to be send to the API. None of the parameters are required. If you submit an empty object, the defaults will be used.\n\n|param|type|default|description|\n|-|-|-|-|\n|sla|object|-|Overwrite the default `sla` settings. Example: `getApiParams( { \"sla\": {\"visualCompleteTime\": 2000} } )`\n|debug|boolean|`false`|Receive extra debug information from the API\n|esTrace|boolean|`false`|Request Elasticsearch query information from the API\n|esCreate|boolean|`true`|Save the result to elasticsearch\n|days|number|`7`|Number of days to calculate the baseline for\n|perc|number|`75`|Percentile of the baseline to be calculated\n|padding|number|`1.2`|Multiplier to calculate extra padding on top of the baseline\n|searchUrl|string|`''`|Wildcard to use for baseline (instead of using the submitted URL)\n|multirun|object|-|Object that holds information for multi-run tests. Mandatory keys are `totalRuns`, `currentRun` and `id`\n|log|object|-|Object that holds the keys to be logged. Can be used to overwrite the defaults or add extra keys!\n\nExample:\n\n```javascript\ngetApiParams( { \"sla\": { \"pageLoadTime\": 5000 }, \"multirun\": {\"totalRuns\": 5, \"currentRun\": 1, \"id\": \"ofjoa90834r0qfh\"}, \"debug\": true})\n```\n\nReturns:\n\n```json\n{\n    \"sla\": {\n        \"pageLoadTime\": 5000\n    },\n    \"baseline\": {\n        \"days\": 7,\n        \"perc\": 75,\n        \"padding\": 1.2\n    },\n    \"flags\": {\n        \"assertBaseline\": true,\n        \"debug\": true,\n        \"esTrace\": false,\n        \"esCreate\": false,\n        \"passOnFailedAssert\": false\n    },\n    \"multirun\": {\n        \"totalRuns\": 5,\n        \"currentRun\": 1,\n        \"id\": \"ofjoa90834r0qfh\"\n    }\n    \"log\": {\n        \"test_info\": \"Sample test_info\",\n        \"env_tester\": \"Sample tester\",\n        \"browser\": \"Sample browser\",\n        \"env_target\": \"Sample target\",\n        \"team\": \"SAMPLE TEAM\"\n    }\n}\n```\n\nNotice that the `sla` and the `flags.debug` keys were changed when compared to the defaults!\n\n### `getInjectJS(injectType, visualCompleteMark, stripQueryString)`\n\nGet the \"inject code\" from the API\n\n|param|type|required|default|description|\n|-|-|-|-|-|\n|injectType|string|Yes|-|The type of measurement you are performing. Valid options are `navtiming` and `usertiming`|\n|visualCompleteMark|No|string|`false`|The name of the visual complete mark|\n|stripQueryString|No|boolean|`false`|Indicates whether you want to strip the querystring from the URL you are testing|\n\nExample:\n\n```javascript\ngetInjectJS( \"navtiming\", \"visual_complete\", true )\n```\n\nReturns:\n\n```json\n{\n    \"status\": 200,\n    \"inject_code\": \"var%20visualCompleteTime%20%3D%200%3B%0Aif%20(performance.getEntriesByName('visual_complete').length)%20%7B%0A%20%20visualCompleteTime%20%3D%20parseInt(performance.getEntriesByName('visual_complete')%5B0%5D.startTime)%3B%0A%20%20window.performance.clearMarks()%3B%0A%7D%3B%0Areturn%20%7Btime%3Anew%20Date().getTime()%2C%20timing%3Awindow.performance.timing%2C%20visualCompleteTime%3A%20visualCompleteTime%2C%20url%3A%20document.location.href.split(%22%3F%22)%5B0%5D%2C%20resources%3A%20window.performance.getEntriesByType('resource')%7D%3B\"\n}\n```\n\n### `navtiming(injectJS, apiParams)`\n\nPost navtiming performance data to the API\n\n|param|type|required|default|description|\n|-|-|-|-|-|\n|injectJS|object|Yes|-|Contains the full response that you received from the browser after injecting the `injectjs` code|\n|apiParams|object|Yes|-|Contains the API params that you retrieved from the `getApiParams()` method|\n\n### `usertiming(injectJS, apiParams)`\n\nPost usertiming performance data to the API\n\n|param|type|required|default|description|\n|-|-|-|-|-|\n|injectJS|object|Yes|-|Contains the full response that you received from the browser after injecting the `injectjs` code|\n|apiParams|object|Yes|-|Contains the API params that you retrieved from the `getApiParams()` method|\n\n### `apitiming(timing, url, apiParams)`\n\nPost apitiming performance data to the API\n\n|param|type|required|default|description|\n|-|-|-|-|-|\n|timing|object|Yes|-|Contains the start- and stop-timestamps that you set before and after running the API test. Example: `{\"startTime\": 1515443109031, \"endTime\": 1515443109046}` |\n|url|string|Yes|-|The URL of the API you're testing|\n|apiParams|object|Yes|-|Contains the API params that you retrieved from the `getApiParams()` method|\n\nFor more information about the API: [https://github.com/godaddy/timings](https://github.com/godaddy/timings/blob/master/README.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgodaddy%2Ftimings-client-js","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fgodaddy%2Ftimings-client-js","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fgodaddy%2Ftimings-client-js/lists"}