diff --git a/CHANGELOG.md b/CHANGELOG.md index 39d4f279..083af2e4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,10 @@ +# [1.27.0](https://github.com/adobe/spacecat-audit-worker/compare/v1.26.5...v1.27.0) (2024-08-26) + + +### Features + +* cwv audit revival ([#378](https://github.com/adobe/spacecat-audit-worker/issues/378)) ([3a27bde](https://github.com/adobe/spacecat-audit-worker/commit/3a27bded17a6efe7354b5533a217e47fc14c2285)) + ## [1.26.5](https://github.com/adobe/spacecat-audit-worker/compare/v1.26.4...v1.26.5) (2024-08-24) diff --git a/package-lock.json b/package-lock.json index 92c9e198..0b477ce5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@adobe/spacecat-audit-worker", - "version": "1.26.5", + "version": "1.27.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@adobe/spacecat-audit-worker", - "version": "1.26.5", + "version": "1.27.0", "license": "Apache-2.0", "dependencies": { "@adobe/fetch": "4.1.8", diff --git a/package.json b/package.json index b18bbdff..4781f484 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@adobe/spacecat-audit-worker", - "version": "1.26.5", + "version": "1.27.0", "description": "SpaceCat Audit Worker", "main": "src/index.js", "type": "module", diff --git a/src/cwv/handler.js b/src/cwv/handler.js index fb842512..0b485ba2 100644 --- a/src/cwv/handler.js +++ b/src/cwv/handler.js @@ -1,5 +1,5 @@ /* - * Copyright 2023 Adobe. All rights reserved. + * Copyright 2024 Adobe. All rights reserved. * This file is licensed to you 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 @@ -10,83 +10,33 @@ * governing permissions and limitations under the License. */ -import RUMAPIClient, { createRUMURL } from '@adobe/spacecat-shared-rum-api-client-v1'; -import { internalServerError, noContent } from '@adobe/spacecat-shared-http-utils'; -import { composeAuditURL } from '@adobe/spacecat-shared-utils'; -import { retrieveSiteBySiteId } from '../utils/data-access.js'; - -const PAGEVIEW_THRESHOLD = 35000; - -export function filterRUMData(data) { - return data.pageviews > PAGEVIEW_THRESHOLD // ignore the pages with low pageviews - && data.url.toLowerCase() !== 'other'; // ignore the combined result +import RUMAPIClient from '@adobe/spacecat-shared-rum-api-client'; +import { getRUMDomainkey } from '../support/utils.js'; +import { AuditBuilder } from '../common/audit-builder.js'; + +const DAILY_THRESHOLD = 1000; +const INTERVAL = 7; // days + +export async function CWVRunner(auditUrl, context, site) { + const rumAPIClient = RUMAPIClient.createFrom(context); + const domainkey = await getRUMDomainkey(site.getBaseURL(), context); + const options = { + domain: auditUrl, + domainkey, + interval: INTERVAL, + granularity: 'hourly', + }; + const cwvData = await rumAPIClient.query('cwv', options); + const auditResult = { + cwv: cwvData.filter((data) => data.pageviews >= DAILY_THRESHOLD * INTERVAL), + }; + + return { + auditResult, + fullAuditRef: auditUrl, + }; } -/** - * url param in run-query@v3/rum-dashboard works in a 'startsWith' fashion. url=domain.com returns - * an empty result whereas url=www.domain.com/ returns the desired result. To catch the redirects - * to subdomains we issue a GET call to the domain, then use the final url after redirects - * @param url - * @returns finalUrl {Promise} - */ - -function processRUMResponse(data) { - return data - .filter(filterRUMData) - .map((row) => ({ - url: row.url, - pageviews: row.pageviews, - CLS: row.avgcls, - INP: row.avginp, - LCP: row.avglcp, - })); -} -export default async function auditCWV(message, context) { - const { type, url: siteId, auditContext = {} } = message; - const { dataAccess, log, sqs } = context; - const { - AUDIT_RESULTS_QUEUE_URL: queueUrl, - } = context.env; - try { - const site = await retrieveSiteBySiteId(dataAccess, siteId, log); - const url = site.getBaseURL(); - - log.info(`Received audit req for domain: ${url}`); - - const rumAPIClient = RUMAPIClient.createFrom(context); - const finalUrl = await composeAuditURL(url); - auditContext.finalUrl = finalUrl; - - const params = { - url: finalUrl, - }; - - const data = await rumAPIClient.getRUMDashboard(params); - const auditResult = processRUMResponse(data); - const fullAuditRef = createRUMURL({ ...params, domainkey: '' }); - - const auditData = { - siteId: site.getId(), - isLive: site.isLive(), - auditedAt: new Date().toISOString(), - auditType: type, - fullAuditRef, - auditResult, - }; - - await dataAccess.addAudit(auditData); - - await sqs.sendMessage(queueUrl, { - type, - url, - auditContext, - auditResult, - }); - - log.info(`Successfully audited ${url} for ${type} type audit`); - return noContent(); - } catch (e) { - log.info(`CWV audit failed for ${siteId} failed due to ${e.message}`); - return internalServerError(`Internal server error: ${e.message}`); - } -} +export default new AuditBuilder() + .withRunner(CWVRunner) + .build(); diff --git a/src/index.js b/src/index.js index 5d932913..8dc5d6e4 100644 --- a/src/index.js +++ b/src/index.js @@ -11,10 +11,10 @@ */ import wrap from '@adobe/helix-shared-wrap'; import { helixStatus } from '@adobe/helix-status'; -import { Response } from '@adobe/fetch'; import secrets from '@adobe/helix-shared-secrets'; import dataAccess from '@adobe/spacecat-shared-data-access'; import { resolveSecretsName, sqsEventAdapter } from '@adobe/spacecat-shared-utils'; +import { internalServerError, notFound, ok } from '@adobe/spacecat-shared-http-utils'; import sqs from './support/sqs.js'; import apex from './apex/handler.js'; @@ -47,6 +47,7 @@ const HANDLERS = { 'experimentation-ess-all': essExperimentationAll, costs, 'structured-data': structuredData, + dummy: (message) => ok(message), }; function getElapsedSeconds(startTime) { @@ -71,7 +72,7 @@ async function run(message, context) { if (!handler) { const msg = `no such audit type: ${type}`; log.error(msg); - return new Response('', { status: 404 }); + return notFound(); } const startTime = process.hrtime(); @@ -84,12 +85,7 @@ async function run(message, context) { return result; } catch (e) { log.error(`Audit failed after ${getElapsedSeconds(startTime)} seconds`, e); - return new Response('', { - status: e.statusCode || 500, - headers: { - 'x-error': 'internal server error', - }, - }); + return internalServerError(); } } diff --git a/src/support/utils.js b/src/support/utils.js index 56de2841..97c68c9e 100644 --- a/src/support/utils.js +++ b/src/support/utils.js @@ -11,7 +11,7 @@ */ import { context as h2, h1 } from '@adobe/fetch'; -import { hasText, resolveCustomerSecretsName } from '@adobe/spacecat-shared-utils'; +import { hasText, prependSchema, resolveCustomerSecretsName } from '@adobe/spacecat-shared-utils'; import URI from 'urijs'; import { JSDOM } from 'jsdom'; import { GetSecretValueCommand, SecretsManagerClient } from '@aws-sdk/client-secrets-manager'; @@ -26,7 +26,7 @@ export const { fetch } = process.env.HELIX_FETCH_FORCE_HTTP1 // weekly pageview threshold to eliminate urls with lack of samples export async function getRUMUrl(url) { - const urlWithScheme = url.startsWith('http') ? url : `https://${url}`; + const urlWithScheme = prependSchema(url); const resp = await fetch(urlWithScheme); const finalUrl = resp.url.split('://')[1]; return finalUrl.endsWith('/') ? finalUrl.slice(0, -1) : /* c8 ignore next */ finalUrl; diff --git a/test/audits/cwv.test.js b/test/audits/cwv.test.js index ae5cf8e3..9beca15e 100644 --- a/test/audits/cwv.test.js +++ b/test/audits/cwv.test.js @@ -15,79 +15,42 @@ import { expect, use } from 'chai'; import sinon from 'sinon'; import sinonChai from 'sinon-chai'; -import { Request } from '@adobe/fetch'; import nock from 'nock'; import { createSite } from '@adobe/spacecat-shared-data-access/src/models/site.js'; -import { main } from '../../src/index.js'; -import { getRUMUrl } from '../../src/support/utils.js'; -import { expectedAuditResult, rumData } from '../fixtures/rum-data.js'; +import { CWVRunner } from '../../src/cwv/handler.js'; +import { rumData } from '../fixtures/rum-data.js'; use(sinonChai); const sandbox = sinon.createSandbox(); + +const baseURL = 'https://spacecat.com'; +const auditUrl = 'www.spacecat.com'; const DOMAIN_REQUEST_DEFAULT_PARAMS = { + domain: auditUrl, + domainkey: 42, interval: 7, - offset: 0, - limit: 101, + granularity: 'hourly', }; -const mockDate = '2023-11-27T12:30:01.124Z'; describe('Index Tests', () => { - const request = new Request('https://space.cat'); - let mockDataAccess; - let context; - let messageBodyJson; - let site; - - before('init', function () { - this.clock = sandbox.useFakeTimers({ - now: new Date(mockDate).getTime(), - }); - }); + const site = createSite({ baseURL }); + const context = { + runtime: { name: 'aws-lambda', region: 'us-east-1' }, + func: { package: 'spacecat-services', version: 'ci', name: 'test' }, + rumApiClient: { + query: sandbox.stub().withArgs('variable-1', sinon.match(DOMAIN_REQUEST_DEFAULT_PARAMS)).resolves(rumData), + }, + }; beforeEach('setup', () => { - site = createSite({ - baseURL: 'https://adobe.com', - }); - - mockDataAccess = { - getSiteByID: sinon.stub(), - addAudit: sinon.stub(), - }; - mockDataAccess.getSiteByID = sinon.stub().withArgs('site-id').resolves(site); - - messageBodyJson = { - type: 'cwv', - url: 'site-id', - auditContext: { - finalUrl: 'adobe.com', - }, - }; - context = { - log: console, - runtime: { - region: 'us-east-1', - }, - dataAccess: mockDataAccess, - env: { - AUDIT_RESULTS_QUEUE_URL: 'queueUrl', - RUM_DOMAIN_KEY: 'domainkey', - }, - invocation: { - event: { - Records: [{ - body: JSON.stringify(messageBodyJson), - }], - }, - }, - sqs: { - sendMessage: sandbox.stub().resolves(), - }, - }; - }); - - after(function () { - this.clock.uninstall(); + nock('https://secretsmanager.us-east-1.amazonaws.com/') + .post('/', (body) => body.SecretId === '/helix-deploy/spacecat-services/customer-secrets/spacecat_com/ci') + .reply(200, { + SecretString: JSON.stringify({ + RUM_DOMAIN_KEY: '42', + }), + }); }); afterEach(() => { @@ -95,76 +58,13 @@ describe('Index Tests', () => { sinon.restore(); }); - it('fetch cwv for base url > process > send results', async () => { - nock('https://adobe.com') - .get('/') - .reply(200); - nock('https://helix-pages.anywhere.run') - .get('/helix-services/run-query@v3/rum-dashboard') - .query({ - ...DOMAIN_REQUEST_DEFAULT_PARAMS, - domainkey: context.env.RUM_DOMAIN_KEY, - url: 'adobe.com', - }) - .reply(200, rumData); - - const resp = await main(request, context); - - const expectedMessage = { - ...messageBodyJson, - url: site.getBaseURL(), - auditResult: expectedAuditResult, - }; - - expect(resp.status).to.equal(204); - expect(mockDataAccess.addAudit).to.have.been.calledOnce; - expect(mockDataAccess.addAudit).to.have.been.calledWith({ - siteId: site.getId(), - isLive: false, - auditedAt: mockDate, - auditType: 'cwv', - fullAuditRef: 'https://helix-pages.anywhere.run/helix-services/run-query@v3/rum-dashboard?interval=7&offset=0&limit=101&url=adobe.com&domainkey=', - auditResult: expectedAuditResult, + it('cwv audit runs rum api client cwv query', async () => { + const result = await CWVRunner('www.spacecat.com', context, site); + expect(result).to.deep.equal({ + auditResult: { + cwv: rumData.filter((data) => data.pageviews >= 7000), + }, + fullAuditRef: auditUrl, }); - expect(context.sqs.sendMessage).to.have.been.calledOnce; - expect(context.sqs.sendMessage).to.have.been - .calledWith(context.env.AUDIT_RESULTS_QUEUE_URL, expectedMessage); - }); - - it('fetch cwv for base url for base url > process > reject', async () => { - nock('https://adobe.com') - .get('/') - .reply(200); - nock('https://helix-pages.anywhere.run') - .get('/helix-services/run-query@v3/rum-dashboard') - .query({ - ...DOMAIN_REQUEST_DEFAULT_PARAMS, - domainkey: context.env.RUM_DOMAIN_KEY, - checkpoint: 404, - url: 'adobe.com', - }) - .replyWithError('Bad request'); - - const resp = await main(request, context); - - expect(resp.status).to.equal(500); - }); - - it('getRUMUrl do not add scheme to urls with a scheme already', async () => { - nock('http://space.cat') - .get('/') - .reply(200); - - const finalUrl = await getRUMUrl('http://space.cat'); - expect(finalUrl).to.eql('space.cat'); - }); - - it('getRUMUrl adds scheme to urls without a scheme', async () => { - nock('https://space.cat') - .get('/') - .reply(200); - - const finalUrl = await getRUMUrl('space.cat'); - expect(finalUrl).to.eql('space.cat'); }); }); diff --git a/test/fixtures/rum-data.js b/test/fixtures/rum-data.js index e1ceca35..de4712fe 100644 --- a/test/fixtures/rum-data.js +++ b/test/fixtures/rum-data.js @@ -10,499 +10,377 @@ * governing permissions and limitations under the License. */ -export const expectedAuditResult = [ +export const rumData = [ { - url: 'https://www.adobe.com/', - pageviews: '36064271', - CLS: 0.148, - INP: 65, - LCP: 5239, + url: 'https://www.aem.live/home', + lcp: 2099.699999988079, + lcpCount: 9, + cls: 0.020660136604802475, + clsCount: 7, + inp: 12, + inpCount: 3, + ttfb: 520.4500000476837, + ttfbCount: 18, + pageviews: 2620, }, { - url: 'https://www.adobe.com/express/feature/image/remove-background', - pageviews: '2737380', - CLS: 0.129, - INP: 95, - LCP: 1423, + url: 'https://www.aem.live/developer/block-collection', + lcp: 512.1249999403954, + lcpCount: 4, + cls: 0.0005409526209424976, + clsCount: 4, + inp: 20, + inpCount: 2, + ttfb: 122.90000003576279, + ttfbCount: 4, + pageviews: 2000, }, { - url: 'https://www.adobe.com/express/', - pageviews: '2703493', - CLS: 0.028, - INP: 79, - LCP: 1869, + url: 'https://www.aem.live/docs/', + lcp: 711.3499999996275, + lcpCount: 15, + cls: 0.011139588793585503, + clsCount: 10, + inp: 36, + inpCount: 8, + ttfb: 96.97500000149012, + ttfbCount: 16, + pageviews: 1910, }, -]; -export const rumData = { - ':names': [ - 'results', - 'meta', - ], - ':type': 'multi-sheet', - ':version': 3, - results: { - limit: 6, - offset: 1, - total: 6, - data: [ - { - url: 'https://www.adobe.com/', - pageviews: '36064271', - pageviews_1: '3549602', - pageviews_diff: '32514669', - lcpgood: 32, - fidgood: 88, - inpgood: 82, - clsgood: 60, - lcpbad: 37, - fidbad: 0, - inpbad: 0, - clsbad: 18, - avglcp: 5239, - avgfid: 6, - avginp: 65, - avgcls: 0.148, - rumshare: '43.455607462', - lcpgood_1: 25, - fidgood_1: 89, - inpgood_1: 83, - clsgood_1: 89, - lcpbad_1: 45, - fidbad_1: 1, - inpbad_1: 3, - clsbad_1: 0, - avglcp_1: 6376, - avgfid_1: 7, - avginp_1: 72, - avgcls_1: 0.01, - rumshare_1: '6.99597117', - url_1: 'https://www.adobe.com/', - }, - { - url: 'https://www.adobe.com/express/feature/image/remove-background', - pageviews: '2737380', - pageviews_1: '2246720', - pageviews_diff: '490660', - lcpgood: 80, - fidgood: 87, - inpgood: 82, - clsgood: 55, - lcpbad: 4, - fidbad: 1, - inpbad: 0, - clsbad: 20, - avglcp: 1423, - avgfid: 10, - avginp: 95, - avgcls: 0.129, - rumshare: '3.298403308', - lcpgood_1: 81, - fidgood_1: 87, - inpgood_1: 78, - clsgood_1: 44, - lcpbad_1: 4, - fidbad_1: 1, - inpbad_1: 4, - clsbad_1: 33, - avglcp_1: 1452, - avgfid_1: 12, - avginp_1: 116, - avgcls_1: 0.774, - rumshare_1: '4.428098797', - url_1: 'https://www.adobe.com/express/feature/image/remove-background', - }, - { - url: 'https://www.adobe.com/express/', - pageviews: '2703493', - pageviews_1: '2996880', - pageviews_diff: '-293387', - lcpgood: 73, - fidgood: 87, - inpgood: 83, - clsgood: 80, - lcpbad: 7, - fidbad: 1, - inpbad: 0, - clsbad: 3, - avglcp: 1869, - avgfid: 8, - avginp: 79, - avgcls: 0.028, - rumshare: '3.257571201', - lcpgood_1: 76, - fidgood_1: 88, - inpgood_1: 84, - clsgood_1: 84, - lcpbad_1: 6, - fidbad_1: 1, - inpbad_1: 2, - clsbad_1: 1, - avglcp_1: 1718, - avgfid_1: 8, - avginp_1: 73, - avgcls_1: 0.029, - rumshare_1: '5.906601945', - url_1: 'https://www.adobe.com/express/', - }, - { - url: 'https://www.adobe.com/acrobat/online/pdf-to-word.html', - pageviews: '6999', - pageviews_1: '1663400', - pageviews_diff: '-301000', - lcpgood: 58, - fidgood: 98, - inpgood: 86, - clsgood: 47, - lcpbad: 30, - fidbad: 1, - inpbad: 0, - clsbad: 36, - avglcp: 5086, - avgfid: 5, - avginp: 112, - avgcls: 0.686, - rumshare: '1.641622525', - lcpgood_1: 59, - fidgood_1: 98, - inpgood_1: 87, - clsgood_1: 46, - lcpbad_1: 30, - fidbad_1: 1, - inpbad_1: 7, - clsbad_1: 36, - avglcp_1: 5332, - avgfid_1: 5, - avginp_1: 112, - avgcls_1: 0.69, - rumshare_1: '3.278423452', - url_1: 'https://www.adobe.com/acrobat/online/pdf-to-word.html', - }, - { - url: 'https://www.adobe.com/acrobat/online/merge-pdf.html', - pageviews: '1', - pageviews_1: '818200', - pageviews_diff: '-134300', - lcpgood: 81, - fidgood: 98, - inpgood: 83, - clsgood: 55, - lcpbad: 11, - fidbad: 1, - inpbad: 0, - clsbad: 29, - avglcp: 2120, - avgfid: 5, - avginp: 144, - avgcls: 0.412, - rumshare: '0.824064625', - lcpgood_1: 81, - fidgood_1: 98, - inpgood_1: 82, - clsgood_1: 46, - lcpbad_1: 10, - fidbad_1: 1, - inpbad_1: 9, - clsbad_1: 42, - avglcp_1: 2056, - avgfid_1: 4, - avginp_1: 152, - avgcls_1: 0.727, - rumshare_1: '1.612604346', - url_1: 'https://www.adobe.com/acrobat/online/merge-pdf.html', - }, - { - url: 'Other', - pageviews: '38797220', - pageviews_1: '38700170', - pageviews_diff: '97050', - lcpgood: 71, - fidgood: 92, - inpgood: 82, - clsgood: 64, - lcpbad: 13, - fidbad: 1, - inpbad: 0, - clsbad: 21, - avglcp: 2656, - avgfid: 10, - avginp: 131, - avgcls: 0.315, - rumshare: '46.74867164', - lcpgood_1: 70, - fidgood_1: 90, - inpgood_1: 80, - clsgood_1: 56, - lcpbad_1: 13, - fidbad_1: 1, - inpbad_1: 5, - clsbad_1: 30, - avglcp_1: 2533, - avgfid_1: 9, - avginp_1: 124, - avgcls_1: 0.418, - rumshare_1: '76.274825622', - url_1: 'Other', - }, - ], - columns: [ - 'url', - 'pageviews', - 'pageviews_1', - 'pageviews_diff', - 'lcpgood', - 'fidgood', - 'inpgood', - 'clsgood', - 'lcpbad', - 'fidbad', - 'inpbad', - 'clsbad', - 'avglcp', - 'avgfid', - 'avginp', - 'avgcls', - 'rumshare', - 'lcpgood_1', - 'fidgood_1', - 'inpgood_1', - 'clsgood_1', - 'lcpbad_1', - 'fidbad_1', - 'inpbad_1', - 'clsbad_1', - 'avglcp_1', - 'avgfid_1', - 'avginp_1', - 'avgcls_1', - 'rumshare_1', - 'url_1', - ], + { + url: 'https://www.aem.live/tools/rum/explorer.html', + lcp: 1111.8000000715256, + lcpCount: 9, + cls: 0.000996222305285266, + clsCount: 7, + inp: 184, + inpCount: 5, + ttfb: 312.69999980926514, + ttfbCount: 9, + pageviews: 1600, + }, + { + url: 'https://www.aem.live/developer/tutorial', + lcp: 1256.0249999985099, + lcpCount: 6, + cls: 0.3156739291116928, + clsCount: 6, + inp: 36, + inpCount: 3, + ttfb: 399.62500001490116, + ttfbCount: 6, + pageviews: 1600, + }, + { + url: 'https://www.aem.live/developer/anatomy-of-a-franklin-project', + lcp: 1360.6000000005588, + lcpCount: 4, + cls: 0.00013092332403036945, + clsCount: 2, + inp: null, + inpCount: 0, + ttfb: 345.69999999962965, + ttfbCount: 4, + pageviews: 1200, + }, + { + url: 'https://www.aem.live/developer/indexing', + lcp: null, + lcpCount: 0, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 317, + ttfbCount: 1, + pageviews: 1000, + }, + { + url: 'https://www.aem.live/docs/custom-headers', + lcp: null, + lcpCount: 0, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 22.69999998807907, + ttfbCount: 1, + pageviews: 900, + }, + { + url: 'https://www.aem.live/docs/dev-collab-and-good-practices', + lcp: 158.60000000149012, + lcpCount: 1, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 34.70000000298023, + ttfbCount: 1, + pageviews: 700, + }, + { + url: 'https://www.aem.live/docs/go-live-checklist', + lcp: 75.5, + lcpCount: 1, + cls: null, + clsCount: 0, + inp: 8, + inpCount: 1, + ttfb: null, + ttfbCount: 0, + pageviews: 600, + }, + { + url: 'https://www.aem.live/developer/keeping-it-100', + lcp: 282.7250000759959, + lcpCount: 2, + cls: 0.006388621736403153, + clsCount: 2, + inp: 22, + inpCount: 2, + ttfb: 48.374999932944775, + ttfbCount: 2, + pageviews: 500, + }, + { + url: 'https://www.aem.live/tools/sidekick/', + lcp: 2756.899999856949, + lcpCount: 1, + cls: 0.0004926924960464029, + clsCount: 1, + inp: null, + inpCount: 0, + ttfb: 612.7749998904765, + ttfbCount: 2, + pageviews: 410, + }, + { + url: 'https://www.aem.live/docs/placeholders', + lcp: 740.875, + lcpCount: 2, + cls: 0.0029431425237193406, + clsCount: 2, + inp: 24, + inpCount: 1, + ttfb: 330, + ttfbCount: 1, + pageviews: 403, + }, + { + url: 'https://www.aem.live/docs/byo-cdn-cloudflare-worker-setup', + lcp: 483.69999998807907, + lcpCount: 1, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 155.69999998807907, + ttfbCount: 1, + pageviews: 400, + }, + { + url: 'https://www.aem.live/docs/davidsmodel', + lcp: 1546.9000000059605, + lcpCount: 3, + cls: 0.7502103183538148, + clsCount: 2, + inp: 24, + inpCount: 1, + ttfb: 1016.2000000234693, + ttfbCount: 3, + pageviews: 300, + }, + { + url: 'https://www.aem.live/docs/setup-customer-sharepoint', + lcp: 361.09999999403954, + lcpCount: 1, + cls: 0.00017381700304902785, + clsCount: 1, + inp: null, + inpCount: 0, + ttfb: 12.899999976158142, + ttfbCount: 1, + pageviews: 300, + }, + { + url: 'https://www.aem.live/docs/sidekick', + lcp: null, + lcpCount: 0, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 18, + ttfbCount: 1, + pageviews: 200, }, - meta: { - limit: 12, - offset: 0, - total: 12, - columns: [ - 'name', - 'value', - 'type', - ], - data: [ - { - name: 'description', - value: 'Get Helix RUM data for a given domain or owner/repo combination', - type: 'query description', - }, - { - name: 'limit', - value: 6, - type: 'request parameter', - }, - { - name: 'interval', - value: 30, - type: 'request parameter', - }, - { - name: 'offset', - value: 1, - type: 'request parameter', - }, - { - name: 'startdate', - value: '2022-02-01', - type: 'request parameter', - }, - { - name: 'enddate', - value: '2022-05-28', - type: 'request parameter', - }, - { - name: 'timezone', - value: 'UTC', - type: 'request parameter', - }, - { - name: 'url', - value: 'www.adobe.com/', - type: 'request parameter', - }, - { - name: 'owner', - value: '-', - type: 'request parameter', - }, - { - name: 'repo', - value: '-', - type: 'request parameter', - }, - { - name: 'device', - value: 'all', - type: 'request parameter', - }, - { - name: 'rising', - value: false, - type: 'request parameter', - }, - { - name: 'avgcls', - value: '75th percentile value of the Cumulative Layout Shift metric in the current period', - type: 'response detail', - }, - { - name: 'avgcls_1', - value: '75th percentile value of the CLS metric in the previous period', - type: 'response detail', - }, - { - name: 'avgfid', - value: '75th percentile value of the First Input Delay metric in milliseconds in the current period', - type: 'response detail', - }, - { - name: 'avgfid_1', - value: '75th percentile value of FID in the previous period', - type: 'response detail', - }, - { - name: 'avginp', - value: '75th percentile value of the Interaction to Next Paint metric in milliseconds in the current period', - type: 'response detail', - }, - { - name: 'avginp_1', - value: '75th percentile of INP in the previous period', - type: 'response detail', - }, - { - name: 'avglcp', - value: '75th percentile of the Largest Contentful Paint metric in milliseconds in the current period', - type: 'response detail', - }, - { - name: 'avglcp_1', - value: '75th percentile of LCP in the previous period', - type: 'response detail', - }, - { - name: 'clsbad', - value: 'percentage of all page views where Cumulative Layout Shift is in the “needs improvement” range in the current period', - type: 'response detail', - }, - { - name: 'clsbad_1', - value: 'percentage of of all page views with bad CLS in the previous period', - type: 'response detail', - }, - { - name: 'clsgood', - value: 'percentage of all page views where the CLS metric is in the “good” range in the current period', - type: 'response detail', - }, - { - name: 'clsgood_1', - value: 'percentage of pageviews with good CLS the the previous period', - type: 'response detail', - }, - { - name: 'fidbad', - value: 'percentage of pageviews with bad FID in the current period', - type: 'response detail', - }, - { - name: 'fidbad_1', - value: 'percentage of pageviews with bad FID in the previous period', - type: 'response detail', - }, - { - name: 'fidgood', - value: 'percentage of pageviews with good FID in the current period', - type: 'response detail', - }, - { - name: 'fidgood_1', - value: 'percentage of pageviews with good FID in the previous period', - type: 'response detail', - }, - { - name: 'inpbad', - value: 'percentage of pageviews with bad INP in the current period', - type: 'response detail', - }, - { - name: 'inpbad_1', - value: 'percentage of pageviews with bad INP in the previous period', - type: 'response detail', - }, - { - name: 'inpgood', - value: 'percentage of pageviews with good INP in the current period', - type: 'response detail', - }, - { - name: 'inpgood_1', - value: 'percentage of pageviews with bad INP in the previous period', - type: 'response detail', - }, - { - name: 'lcpbad', - value: 'percentage of pageviews with bad LCP in the current period', - type: 'response detail', - }, - { - name: 'lcpbad_1', - value: 'percentage of pageviews with bad LCP in the previous period', - type: 'response detail', - }, - { - name: 'lcpgood', - value: 'percentage of pageviews with good LCP in the current period', - type: 'response detail', - }, - { - name: 'lcpgood_1', - value: 'percentage of pageviews with good LCP in the current period', - type: 'response detail', - }, - { - name: 'pageviews', - value: 'estimated number of pageviews in the current period', - type: 'response detail', - }, - { - name: 'pageviews_1', - value: 'estimated number of pageviews in the previous period', - type: 'response detail', - }, - { - name: 'pageviews_diff', - value: 'difference in pageviews between the current and previous period. If the parameter rising is true, then pages will be ranked according to this value', - type: 'response detail', - }, - { - name: 'rumshare', - value: 'percentage of all traffic for the given domain that is going to this url in the current period', - type: 'response detail', - }, - { - name: 'rumshare_1', - value: 'percentage of of all traffic in the previous domain that is going to this url in the previous period', - type: 'response detail', - }, - { - name: 'url', - value: 'the URL of the page that is getting traffic', - type: 'response detail', - }, - { - name: 'url_1', - value: 'the URL of the page that is getting traffic in the previous period (these last two values are always the same)', - type: 'response detail', - }, - ], + { + url: 'https://www.aem.live/developer/web-components', + lcp: 612.2000000476837, + lcpCount: 1, + cls: 0.00007814911374216038, + clsCount: 1, + inp: null, + inpCount: 0, + ttfb: 273.4000000357628, + ttfbCount: 1, + pageviews: 200, + }, + { + url: 'https://www.aem.live/docs/authentication-setup-site', + lcp: 639.1999999284744, + lcpCount: 1, + cls: null, + clsCount: 0, + inp: 8, + inpCount: 1, + ttfb: 2551.824999988079, + ttfbCount: 2, + pageviews: 200, + }, + { + url: 'https://www.aem.live/developer/rum', + lcp: 786.1999999992549, + lcpCount: 2, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 261.55000000074506, + ttfbCount: 2, + pageviews: 200, + }, + { + url: 'https://www.aem.live/developer/block-collection/section-metadata', + lcp: null, + lcpCount: 0, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 274.10000002384186, + ttfbCount: 1, + pageviews: 200, + }, + { + url: 'https://www.aem.live/vip/intake', + lcp: 28, + lcpCount: 1, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: null, + ttfbCount: 0, + pageviews: 200, + }, + { + url: 'https://www.aem.live/docs/sidekick-extension', + lcp: 433.70000000298023, + lcpCount: 1, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 334.30000000447035, + ttfbCount: 1, + pageviews: 110, + }, + { + url: 'https://www.aem.live/docs/rum', + lcp: 78.79999995231628, + lcpCount: 1, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 12.100000023841858, + ttfbCount: 1, + pageviews: 110, + }, + { + url: 'https://www.aem.live/developer/block-collection/breadcrumbs', + lcp: 45.39999997615814, + lcpCount: 1, + cls: 0.000014899872841139986, + clsCount: 1, + inp: 24, + inpCount: 1, + ttfb: 9.100000023841858, + ttfbCount: 1, + pageviews: 100, + }, + { + url: 'https://www.aem.live/developer/block-collection/headings', + lcp: null, + lcpCount: 0, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 288.10000002384186, + ttfbCount: 1, + pageviews: 100, + }, + { + url: 'https://www.aem.live/developer/github-actions', + lcp: null, + lcpCount: 0, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 56.59999999962747, + ttfbCount: 1, + pageviews: 100, + }, + { + url: 'https://www.aem.live/developer/importer', + lcp: 1345.7999999523163, + lcpCount: 1, + cls: 0.07786671987900227, + clsCount: 1, + inp: 56, + inpCount: 1, + ttfb: 118.89999997615814, + ttfbCount: 1, + pageviews: 100, }, -}; + { + url: 'https://www.aem.live/developer/configuring-aem-assets-sidekick-plugin', + lcp: null, + lcpCount: 0, + cls: null, + clsCount: 0, + inp: null, + inpCount: 0, + ttfb: 22, + ttfbCount: 1, + pageviews: 100, + }, + { + url: 'https://www.aem.live/tools/rum/list.html', + lcp: 1182.5, + lcpCount: 1, + cls: null, + clsCount: 0, + inp: 8, + inpCount: 1, + ttfb: 433.2999997138977, + ttfbCount: 1, + pageviews: 100, + }, + { + url: 'https://www.aem.live/developer/forms', + lcp: 954, + lcpCount: 1, + cls: 0.0005954693086687166, + clsCount: 1, + inp: null, + inpCount: 0, + ttfb: 190.09999999403954, + ttfbCount: 1, + pageviews: 100, + }, +]; diff --git a/test/index.test.js b/test/index.test.js index 6f3769dd..01addaa5 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -29,8 +29,8 @@ describe('Index Tests', () => { beforeEach('setup', () => { messageBodyJson = { - type: 'cwv', - url: 'adobe.com', + type: 'dummy', + url: 'site-id', auditContext: { key: 'value', }, @@ -80,10 +80,8 @@ describe('Index Tests', () => { expect(resp.status).to.equal(500); }); - it('fails when missing required env variables', async () => { + it('happy path', async () => { const resp = await main(request, context); - - expect(resp.status).to.equal(500); - expect(resp.headers.plain()['x-error']).to.equal('internal server error'); + expect(resp.status).to.equal(200); }); });