diff --git a/frontend/cypress/CustomFunctions/uncaughtExpection.ts b/frontend/cypress/CustomFunctions/uncaughtExpection.ts new file mode 100644 index 0000000000..341ddd8cee --- /dev/null +++ b/frontend/cypress/CustomFunctions/uncaughtExpection.ts @@ -0,0 +1,14 @@ +const resizeObserverLoopErrRe = /ResizeObserver loop limit exceeded/; + +const unCaughtExpection = () => { + cy.on('uncaught:exception', (err) => { + if (resizeObserverLoopErrRe.test(err.message)) { + // returning false here prevents Cypress from + // failing the test + return false; + } + return true; + }); +}; + +export default unCaughtExpection; diff --git a/frontend/cypress/fixtures/trace/initialAggregates.json b/frontend/cypress/fixtures/trace/initialAggregates.json new file mode 100644 index 0000000000..b029e9de64 --- /dev/null +++ b/frontend/cypress/fixtures/trace/initialAggregates.json @@ -0,0 +1,35 @@ +{ + "items": { + "1644926280000000000": { "timestamp": 1644926280000000000, "value": 787 }, + "1644926340000000000": { "timestamp": 1644926340000000000, "value": 2798 }, + "1644926400000000000": { "timestamp": 1644926400000000000, "value": 2828 }, + "1644926460000000000": { "timestamp": 1644926460000000000, "value": 2926 }, + "1644926520000000000": { "timestamp": 1644926520000000000, "value": 2932 }, + "1644926580000000000": { "timestamp": 1644926580000000000, "value": 2842 }, + "1644926640000000000": { "timestamp": 1644926640000000000, "value": 2966 }, + "1644926700000000000": { "timestamp": 1644926700000000000, "value": 2782 }, + "1644926760000000000": { "timestamp": 1644926760000000000, "value": 2843 }, + "1644926820000000000": { "timestamp": 1644926820000000000, "value": 2864 }, + "1644926880000000000": { "timestamp": 1644926880000000000, "value": 2777 }, + "1644926940000000000": { "timestamp": 1644926940000000000, "value": 2820 }, + "1644927000000000000": { "timestamp": 1644927000000000000, "value": 2579 }, + "1644927060000000000": { "timestamp": 1644927060000000000, "value": 2681 }, + "1644927120000000000": { "timestamp": 1644927120000000000, "value": 2828 }, + "1644927180000000000": { "timestamp": 1644927180000000000, "value": 2975 }, + "1644927240000000000": { "timestamp": 1644927240000000000, "value": 2934 }, + "1644927300000000000": { "timestamp": 1644927300000000000, "value": 2793 }, + "1644927360000000000": { "timestamp": 1644927360000000000, "value": 2913 }, + "1644927420000000000": { "timestamp": 1644927420000000000, "value": 2621 }, + "1644927480000000000": { "timestamp": 1644927480000000000, "value": 2631 }, + "1644927540000000000": { "timestamp": 1644927540000000000, "value": 2924 }, + "1644927600000000000": { "timestamp": 1644927600000000000, "value": 2576 }, + "1644927660000000000": { "timestamp": 1644927660000000000, "value": 2878 }, + "1644927720000000000": { "timestamp": 1644927720000000000, "value": 2737 }, + "1644927780000000000": { "timestamp": 1644927780000000000, "value": 2621 }, + "1644927840000000000": { "timestamp": 1644927840000000000, "value": 2823 }, + "1644927900000000000": { "timestamp": 1644927900000000000, "value": 3081 }, + "1644927960000000000": { "timestamp": 1644927960000000000, "value": 2883 }, + "1644928020000000000": { "timestamp": 1644928020000000000, "value": 2823 }, + "1644928080000000000": { "timestamp": 1644928080000000000, "value": 455 } + } +} diff --git a/frontend/cypress/fixtures/trace/initialSpanFilter.json b/frontend/cypress/fixtures/trace/initialSpanFilter.json new file mode 100644 index 0000000000..26bed66ae9 --- /dev/null +++ b/frontend/cypress/fixtures/trace/initialSpanFilter.json @@ -0,0 +1,19 @@ +{ + "serviceName": { + "customer": 1642, + "driver": 1642, + "frontend": 39408, + "mysql": 1642, + "redis": 22167, + "route": 16420 + }, + "status": { "error": 4105, "ok": 78816 }, + "duration": { "maxDuration": 1253979000, "minDuration": 415000 }, + "operation": {}, + "httpCode": {}, + "httpUrl": {}, + "httpMethod": {}, + "httpRoute": {}, + "httpHost": {}, + "component": {} +} diff --git a/frontend/cypress/fixtures/trace/initialSpans.json b/frontend/cypress/fixtures/trace/initialSpans.json new file mode 100644 index 0000000000..9b15100752 --- /dev/null +++ b/frontend/cypress/fixtures/trace/initialSpans.json @@ -0,0 +1,105 @@ +{ + "spans": [ + { + "timestamp": "2022-02-15T12:16:09.542074Z", + "spanID": "303b39065c6f5df5", + "traceID": "00000000000000007fc49fab3cb75958", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 313418000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:08.84038Z", + "spanID": "557e8303bc802992", + "traceID": "000000000000000079310bd1d435a92b", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 318203000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:08.867689Z", + "spanID": "347113dd916dd20e", + "traceID": "00000000000000004c22c0409cee0f66", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 512810000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:07.060882Z", + "spanID": "0a8d07f72aa1339b", + "traceID": "0000000000000000488e11a35959de96", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 588705000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:07.134107Z", + "spanID": "0acd4ec344675998", + "traceID": "00000000000000000292efc7945d9bfa", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 801632000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:06.474095Z", + "spanID": "3ae72e433301822a", + "traceID": "00000000000000001ac3004ff1b7eefe", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 306650000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:06.996246Z", + "spanID": "1d765427af673039", + "traceID": "00000000000000002e78f59fabbcdecf", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 311469000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:05.324296Z", + "spanID": "0987c90d83298a1d", + "traceID": "0000000000000000077bcb960609a350", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 290680000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:02.458221Z", + "spanID": "5b0d0d403dd9acf4", + "traceID": "00000000000000007ae5b0aa69242556", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 262763000, + "httpCode": "200", + "httpMethod": "GET" + }, + { + "timestamp": "2022-02-15T12:16:00.584939Z", + "spanID": "3beafb277a76b9b4", + "traceID": "00000000000000000ab44953c2fd949e", + "serviceName": "customer", + "operation": "HTTP GET /customer", + "durationNano": 302851000, + "httpCode": "200", + "httpMethod": "GET" + } + ], + "totalSpans": 82921 +} diff --git a/frontend/cypress/integration/trace/index.spec.ts b/frontend/cypress/integration/trace/index.spec.ts new file mode 100644 index 0000000000..3ca79ecdce --- /dev/null +++ b/frontend/cypress/integration/trace/index.spec.ts @@ -0,0 +1,154 @@ +import ROUTES from 'constants/routes'; +import { TraceFilterEnum } from 'types/reducer/trace'; +import TableInitialResponse from '../../fixtures/trace/initialSpans.json'; +import FilterInitialResponse from '../../fixtures/trace/initialSpanFilter.json'; +import GraphInitialResponse from '../../fixtures/trace/initialAggregates.json'; +import { AppState } from 'store/reducers'; + +describe('Trace', () => { + beforeEach(() => { + window.localStorage.setItem('isLoggedIn', 'yes'); + + cy + .intercept('POST', '**/aggregates', { + fixture: 'trace/initialAggregates', + }) + .as('Graph'); + + cy + .intercept('POST', '**/getFilteredSpans', { + fixture: 'trace/initialSpans', + }) + .as('Table'); + + cy + .intercept('POST', '**/api/v1/getSpanFilters', { + fixture: 'trace/initialSpanFilter', + }) + .as('Filters'); + + cy.visit(Cypress.env('baseUrl') + `${ROUTES.TRACE}`); + }); + + it('First Initial Load should go with 3 AJAX request', () => { + cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { + const [filter, graph, table] = e; + + const { body: filterBody } = filter.request; + const { body: graphBody } = graph.request; + const { body: tableBody } = table.request; + + expect(filterBody.exclude.length).to.equal(0); + expect(filterBody.getFilters.length).to.equal(3); + filterBody.getFilters.forEach((filter: TraceFilterEnum) => { + expect(filter).to.be.oneOf(['duration', 'status', 'serviceName']); + }); + + expect(graphBody.function).to.be.equal('count'); + expect(graphBody.exclude.length).to.be.equal(0); + expect(typeof graphBody.exclude).to.be.equal('object'); + + expect(tableBody.tags.length).to.be.equal(0); + expect(typeof tableBody.tags).equal('object'); + + expect(tableBody.exclude.length).equals(0); + }); + }); + + it('Render Time Request Response In All 3 Request', () => { + cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { + const [filter, graph, table] = e; + + expect(filter.response?.body).to.be.not.undefined; + expect(filter.response?.body).to.be.not.NaN; + + expect(JSON.stringify(filter.response?.body)).to.be.equals( + JSON.stringify(FilterInitialResponse), + ); + + expect(JSON.stringify(graph.response?.body)).to.be.equals( + JSON.stringify(GraphInitialResponse), + ); + + expect(JSON.stringify(table.response?.body)).to.be.equals( + JSON.stringify(TableInitialResponse), + ); + }); + cy.get('@Filters.all').should('have.length', 1); + cy.get('@Graph.all').should('have.length', 1); + cy.get('@Table.all').should('have.length', 1); + }); + + it('Clear All', () => { + cy.wait(['@Filters', '@Graph', '@Table']); + + expect(cy.findAllByText('Clear All')).not.to.be.undefined; + + cy + .window() + .its('store') + .invoke('getState') + .then((e: AppState) => { + const { traces } = e; + expect(traces.isFilterExclude.get('status')).to.be.undefined; + expect(traces.selectedFilter.size).to.be.equals(0); + }); + + cy.findAllByText('Clear All').then((e) => { + const [firstStatusClear] = e; + + firstStatusClear.click(); + + cy.wait(['@Filters', '@Graph', '@Table']); + + // insuring the api get call + cy.get('@Filters.all').should('have.length', 2); + cy.get('@Graph.all').should('have.length', 2); + cy.get('@Table.all').should('have.length', 2); + + cy + .window() + .its('store') + .invoke('getState') + .then((e: AppState) => { + const { traces } = e; + + expect(traces.isFilterExclude.get('status')).to.be.equals(false); + expect(traces.userSelectedFilter.get('status')).to.be.undefined; + expect(traces.selectedFilter.size).to.be.equals(0); + }); + }); + }); + + it('Un Selecting one option from status', () => { + cy.wait(['@Filters', '@Graph', '@Table']); + + cy.get('input[type="checkbox"]').then((e) => { + const [errorCheckbox] = e; + errorCheckbox.click(); + + cy.wait(['@Filters', '@Graph', '@Table']).then((e) => { + const [filter, graph, table] = e; + const filterBody = filter.request.body; + const graphBody = graph.request.body; + const tableBody = table.request.body; + + expect(filterBody.exclude).not.to.be.undefined; + expect(filterBody.exclude.length).not.to.be.equal(0); + expect(filterBody.exclude[0] === 'status').to.be.true; + + expect(graphBody.exclude).not.to.be.undefined; + expect(graphBody.exclude.length).not.to.be.equal(0); + expect(graphBody.exclude[0] === 'status').to.be.true; + + expect(tableBody.exclude).not.to.be.undefined; + expect(tableBody.exclude.length).not.to.be.equal(0); + expect(tableBody.exclude[0] === 'status').to.be.true; + }); + + cy.get('@Filters.all').should('have.length', 2); + cy.get('@Graph.all').should('have.length', 2); + cy.get('@Table.all').should('have.length', 2); + }); + }); +}); diff --git a/frontend/src/container/Trace/Graph/index.tsx b/frontend/src/container/Trace/Graph/index.tsx index a91fe78930..efc8a9d137 100644 --- a/frontend/src/container/Trace/Graph/index.tsx +++ b/frontend/src/container/Trace/Graph/index.tsx @@ -40,7 +40,7 @@ const TraceGraph = () => { return ( - + ); }; diff --git a/frontend/src/container/Trace/TraceGraphFilter/index.tsx b/frontend/src/container/Trace/TraceGraphFilter/index.tsx index bd06764aad..e6aad7374a 100644 --- a/frontend/src/container/Trace/TraceGraphFilter/index.tsx +++ b/frontend/src/container/Trace/TraceGraphFilter/index.tsx @@ -56,6 +56,7 @@ const TraceGraphFilter = () => { selectedFunction === e.key)?.displayValue} onChange={onClickSelectedFunctionHandler} > @@ -69,6 +70,7 @@ const TraceGraphFilter = () => { selectedGroupBy === e.key)?.displayValue} onChange={onClickSelectedGroupByHandler} >