Skip to content

Commit

Permalink
feat: E2E Trace-Based Testing (#32)
Browse files Browse the repository at this point in the history
* feat: E2E Trace-Based Testing

* adding npm packages

* adding npm packages

* updates

* adding custom config support
  • Loading branch information
xoscar authored Dec 13, 2023
1 parent 7420847 commit 91dd3db
Show file tree
Hide file tree
Showing 23 changed files with 4,900 additions and 26,835 deletions.
2 changes: 2 additions & 0 deletions .env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
TRACETEST_API_TOKEN=
POKESHOP_DEMO_URL=
15 changes: 13 additions & 2 deletions .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
"root": true,
"globals": {},
"rules": {
"no-unused-vars": "error",
"quotes": ["error", "single", { "avoidEscape": true }],
"no-unused-vars": "off",
"@typescript-eslint/no-explicit-any": "off",
"max-len": [
"error",
{
Expand All @@ -15,7 +17,16 @@
"ignoreStrings": true,
"ignoreTemplateLiterals": true
}
]
],
"@typescript-eslint/ban-types": [
"warn",
{
"types": {
"Function": null
}
}
],
"@typescript-eslint/no-this-alias": "off"
},
"parser": "@typescript-eslint/parser",
"env": {},
Expand Down
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,7 @@ helm-chart/charts/
node_modules/
api/.build/
.idea/
.DS_Store
.env

cypress/screenshots
1 change: 1 addition & 0 deletions api/.env
Original file line number Diff line number Diff line change
Expand Up @@ -8,3 +8,4 @@ RPC_PORT=8082
KAFKA_BROKER=localhost:29092
KAFKA_TOPIC=pokemon
KAFKA_CLIENT_ID=streaming-worker
HTTP_COLLECTOR_ENDPOINT=http://localhost:4318/v1/traces
5 changes: 3 additions & 2 deletions api/src/scripts/saveConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,14 @@ import { resolve } from 'path';
import { writeFileSync } from 'fs';

const PATH = '../ui/config.json';
const { ZIPKIN_URL = '' } = process.env;
const { SERVICE_NAME = '', HTTP_COLLECTOR_ENDPOINT = '' } = process.env;

const saveConfig = () => {
writeFileSync(
resolve(__dirname, PATH),
JSON.stringify({
ZIPKIN_URL,
HTTP_COLLECTOR_ENDPOINT,
SERVICE_NAME,
})
);
};
Expand Down
4 changes: 4 additions & 0 deletions collector.config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@ receivers:
protocols:
grpc:
http:
cors:
allowed_origins:
- "http://*"
- "https://*"

processors:
batch:
Expand Down
17 changes: 17 additions & 0 deletions cypress.config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { defineConfig } from 'cypress';
import { config } from 'dotenv';

config();

module.exports = defineConfig({
chromeWebSecurity: false,
e2e: {
baseUrl: process.env.POKESHOP_DEMO_URL || 'http://localhost:3000',
env: {
TRACETEST_API_TOKEN: process.env.TRACETEST_API_TOKEN,
},
setupNodeEvents() {
// implement node event listeners here
},
},
});
80 changes: 80 additions & 0 deletions cypress/e2e/1-getting-started/home.cy.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
import Tracetest from '@tracetest/cypress';

const TRACETEST_API_TOKEN = Cypress.env('TRACETEST_API_TOKEN') || '';

const tracetest = Tracetest();

const definition = `
type: Test
spec:
id: aW1wb3J0cyBhIHBva2Vtb24=
name: imports a pokemon
trigger:
type: traceid
traceid:
id: \${var:TRACE_ID}
specs:
- selector: span[tracetest.span.type="http"]
name: "All HTTP Spans: Status code is not 400"
assertions:
- attr:http.status_code != 400
- selector: span[tracetest.span.type="database"]
name: "All Database Spans: Processing time is less than 100ms"
assertions:
- attr:tracetest.span.duration < 100ms
outputs:
- name: MY_OUTPUT
selector: span[tracetest.span.type="general" name="Tracetest trigger"]
value: attr:name
- name: MY_OUTPUT_2
selector: span[tracetest.span.type="general" name="Tracetest trigger"]
value: attr:name
`;

describe('Home', { defaultCommandTimeout: 60000 }, () => {
before(done => {
tracetest.configure(TRACETEST_API_TOKEN).then(() => done());
});

beforeEach(() => {
cy.visit('/', {
onBeforeLoad: win => tracetest.capture(win.document),
});
});

afterEach(done => {
const definition = Cypress.env('definition') || '';
tracetest.runTest(definition).then(() => done());
});


// uncomment to wait for trace tests to be done
after(done => {
tracetest.summary().then(() => done());
});

it('create a pokemon', () => {
cy.get('[data-cy="create-pokemon-button"]').should('be.visible').click();
cy.get('[data-cy="create-pokemon-modal"]').should('be.visible');
cy.get('#name').type('Pikachu');
cy.get('#type').type('Electric');
cy.get('#imageUrl').type('https://oyster.ignimgs.com/mediawiki/apis.ign.com/pokemon-blue-version/8/89/Pikachu.jpg');

cy.get('button').contains('OK').click();
});

it('imports a pokemon', { env: { definition } }, () => {
cy.get('[data-cy="import-pokemon-button"]').click();
cy.get('[data-cy="import-pokemon-form"]').should('be.visible');

cy.get('[id="id"]')
.last()
.type(Math.floor(Math.random() * 101).toString());
cy.get('button').contains('OK').click({ force: true });
});

it('deletes a pokemon (2)', () => {
cy.get('[data-cy="pokemon-list"]').should('be.visible');
cy.get('[data-cy="pokemon-card"]').first().click().get('[data-cy="delete-pokemon-button"]').first().click();
});
});
25 changes: 25 additions & 0 deletions cypress/support/commands.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// ***********************************************
// This example commands.js shows you how to
// create various custom commands and overwrite
// existing commands.
//
// For more comprehensive examples of custom
// commands please read more here:
// https://on.cypress.io/custom-commands
// ***********************************************
//
//
// -- This is a parent command --
// Cypress.Commands.add('login', (email, password) => { ... })
//
//
// -- This is a child command --
// Cypress.Commands.add('drag', { prevSubject: 'element'}, (subject, options) => { ... })
//
//
// -- This is a dual command --
// Cypress.Commands.add('dismiss', { prevSubject: 'optional'}, (subject, options) => { ... })
//
//
// -- This will overwrite an existing command --
// Cypress.Commands.overwrite('visit', (originalFn, url, options) => { ... })
20 changes: 20 additions & 0 deletions cypress/support/e2e.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// ***********************************************************
// This example support/e2e.js is processed and
// loaded automatically before your test files.
//
// This is a great place to put global configuration and
// behavior that modifies Cypress.
//
// You can change the location of this file or turn off
// automatically serving support files with the
// 'supportFile' configuration option.
//
// You can read more here:
// https://on.cypress.io/configuration
// ***********************************************************

// Import commands.js using ES2015 syntax:
import './commands'

// Alternatively you can use CommonJS syntax:
// require('./commands')
4 changes: 2 additions & 2 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,9 @@ services:
- 'host.docker.internal:host-gateway'
ports:
- 55679:55679
- 4317:4317
- 8888:8888
- 4317:4317
- 4318:4318
command:
- '--config'
- '/otel-local-config.yaml'
Expand Down Expand Up @@ -100,7 +101,6 @@ services:
condition: service_healthy
otel-collector:
condition: service_started

rpc:
build: .
environment:
Expand Down
Loading

0 comments on commit 91dd3db

Please sign in to comment.