mirror of
https://github.com/graphql-hive/console
synced 2026-04-21 14:37:17 +00:00
317 lines
9.9 KiB
TypeScript
317 lines
9.9 KiB
TypeScript
import {
|
|
createProject,
|
|
createUserAndOrganization,
|
|
generateRandomSlug,
|
|
waitForOrganizationPage,
|
|
waitForProjectPage,
|
|
waitForTargetPage,
|
|
} from '../support/testkit';
|
|
import type { Report } from './../../packages/libraries/core/src/client/usage.js';
|
|
|
|
function createRegistryAccessToken(params: {
|
|
organizationSlug: string;
|
|
projectSlug: string;
|
|
targetSlug: string;
|
|
}) {
|
|
// Visit Registry Tokens settings
|
|
cy.get(
|
|
`a[href="/${params.organizationSlug}/${params.projectSlug}/${params.targetSlug}/settings"]`,
|
|
).click();
|
|
cy.get('[data-cy="target-settings-registry-token-link"]').click();
|
|
// Open the form
|
|
cy.get('[data-cy="target-settings-registry-token"] [data-cy="new-button"]').click();
|
|
// Fill in the token description
|
|
cy.get('[data-cy="create-registry-token-form"] [data-cy="description"]').type('test-token');
|
|
// Pick the permissions
|
|
cy.get('[data-cy="registry-access-scope"] [data-cy="select-trigger"]').click();
|
|
cy.get(
|
|
'[data-cy="registry-access-scope-select-content"] [data-cy="select-option-REGISTRY_WRITE"]',
|
|
).click();
|
|
// Submit
|
|
cy.get('[data-cy="create-registry-token-form"] [data-cy="submit"]').click();
|
|
|
|
// assert the token is created
|
|
cy.get('[data-cy="registry-token-created"] input[type="text"]')
|
|
.invoke('val')
|
|
.then(value => {
|
|
if (typeof value !== 'string') {
|
|
throw new Error('Expected a string');
|
|
}
|
|
|
|
return value;
|
|
})
|
|
.as('token');
|
|
cy.get('@token').should('have.length', 32);
|
|
|
|
// close the modal
|
|
cy.get('[data-cy="registry-token-created"] [data-cy="close"]').contains('Ok, got it!').click();
|
|
}
|
|
|
|
function sendUsageReport(params: { report: Report }) {
|
|
// send a usage report
|
|
cy.get('@token')
|
|
.then(async token => {
|
|
const res = await fetch(`http://localhost:8081`, {
|
|
method: 'POST',
|
|
body: JSON.stringify(params.report),
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
Accept: 'application/json',
|
|
// it is a string, Cypress Hill just doesn't know it
|
|
Authorization: `Bearer ${token as unknown as string}`,
|
|
},
|
|
});
|
|
|
|
expect(res.status).to.equal(200);
|
|
})
|
|
.wait(2000);
|
|
}
|
|
|
|
describe('usage reporting', () => {
|
|
it('usage report should be visible in Insights', () => {
|
|
const organizationSlug = generateRandomSlug();
|
|
const projectSlug = generateRandomSlug();
|
|
const targetSlug = 'development';
|
|
|
|
createUserAndOrganization(organizationSlug);
|
|
waitForOrganizationPage(organizationSlug);
|
|
|
|
createProject(projectSlug);
|
|
waitForProjectPage(projectSlug);
|
|
|
|
// go to the development target
|
|
cy.get(`a[href="/${organizationSlug}/${projectSlug}/${targetSlug}"]`).click();
|
|
waitForTargetPage(targetSlug);
|
|
|
|
createRegistryAccessToken({ organizationSlug, projectSlug, targetSlug });
|
|
|
|
sendUsageReport({
|
|
report: {
|
|
size: 1,
|
|
map: {
|
|
op1: {
|
|
operation: 'query ping { ping }',
|
|
operationName: 'ping',
|
|
fields: ['Query', 'Query.ping'],
|
|
},
|
|
},
|
|
operations: [
|
|
{
|
|
operationMapKey: 'op1',
|
|
timestamp: Date.now(),
|
|
execution: {
|
|
ok: true,
|
|
duration: 200_000_000,
|
|
errorsTotal: 0,
|
|
},
|
|
metadata: {
|
|
client: {
|
|
name: 'ios',
|
|
version: 'v1.2.3',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
// visit Insights
|
|
cy.visit(`/${organizationSlug}/${projectSlug}/${targetSlug}/insights`);
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_ping');
|
|
// visit Insights of "unknown" client
|
|
cy.visit(`/${organizationSlug}/${projectSlug}/${targetSlug}/insights/client/ios`);
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_ping');
|
|
cy.get('h3').contains('Versions').parent().get('p').contains('v1.2.3');
|
|
});
|
|
|
|
it('usage report with "unknown" client should be visible in Insights', () => {
|
|
const organizationSlug = generateRandomSlug();
|
|
const projectSlug = generateRandomSlug();
|
|
const targetSlug = 'development';
|
|
|
|
createUserAndOrganization(organizationSlug);
|
|
waitForOrganizationPage(organizationSlug);
|
|
|
|
createProject(projectSlug);
|
|
waitForProjectPage(projectSlug);
|
|
|
|
// go to the development target
|
|
cy.get(`a[href="/${organizationSlug}/${projectSlug}/${targetSlug}"]`).click();
|
|
waitForTargetPage(targetSlug);
|
|
|
|
createRegistryAccessToken({ organizationSlug, projectSlug, targetSlug });
|
|
|
|
sendUsageReport({
|
|
report: {
|
|
size: 1,
|
|
map: {
|
|
op1: {
|
|
operation: 'query ping { ping }',
|
|
operationName: 'ping',
|
|
fields: ['Query', 'Query.ping'],
|
|
},
|
|
},
|
|
operations: [
|
|
{
|
|
operationMapKey: 'op1',
|
|
timestamp: Date.now(),
|
|
execution: {
|
|
ok: true,
|
|
duration: 200_000_000,
|
|
errorsTotal: 0,
|
|
},
|
|
metadata: {
|
|
client: {
|
|
name: 'unknown',
|
|
version: 'v1.2.3',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
// visit Insights
|
|
cy.visit(`/${organizationSlug}/${projectSlug}/${targetSlug}/insights`);
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_ping');
|
|
// visit Insights of "unknown" client
|
|
cy.visit(`/${organizationSlug}/${projectSlug}/${targetSlug}/insights/client/unknown`);
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_ping');
|
|
cy.get('h3').contains('Versions').parent().get('p').contains('v1.2.3');
|
|
});
|
|
|
|
it('usage report with missing client name should be visible in Insights', () => {
|
|
const organizationSlug = generateRandomSlug();
|
|
const projectSlug = generateRandomSlug();
|
|
const targetSlug = 'development';
|
|
|
|
createUserAndOrganization(organizationSlug);
|
|
waitForOrganizationPage(organizationSlug);
|
|
|
|
createProject(projectSlug);
|
|
waitForProjectPage(projectSlug);
|
|
|
|
// go to the development target
|
|
cy.get(`a[href="/${organizationSlug}/${projectSlug}/${targetSlug}"]`).click();
|
|
waitForTargetPage(targetSlug);
|
|
|
|
createRegistryAccessToken({ organizationSlug, projectSlug, targetSlug });
|
|
|
|
sendUsageReport({
|
|
report: {
|
|
size: 1,
|
|
map: {
|
|
op1: {
|
|
operation: 'query ping { ping }',
|
|
operationName: 'ping',
|
|
fields: ['Query', 'Query.ping'],
|
|
},
|
|
},
|
|
operations: [
|
|
{
|
|
operationMapKey: 'op1',
|
|
timestamp: Date.now(),
|
|
execution: {
|
|
ok: true,
|
|
duration: 200_000_000,
|
|
errorsTotal: 0,
|
|
},
|
|
metadata: {
|
|
client: {
|
|
name: undefined,
|
|
version: 'v1.2.3',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
// visit Insights
|
|
cy.visit(`/${organizationSlug}/${projectSlug}/${targetSlug}/insights`);
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_ping');
|
|
// visit Insights of "unknown" client (we use "unknown" as a fallback for missing client name)
|
|
cy.visit(`/${organizationSlug}/${projectSlug}/${targetSlug}/insights/client/unknown`);
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_ping');
|
|
cy.get('h3').contains('Versions').parent().get('p').contains('v1.2.3');
|
|
});
|
|
|
|
it('usage report with missing and "unknown" client names should be visible in Insights', () => {
|
|
const organizationSlug = generateRandomSlug();
|
|
const projectSlug = generateRandomSlug();
|
|
const targetSlug = 'development';
|
|
|
|
createUserAndOrganization(organizationSlug);
|
|
waitForOrganizationPage(organizationSlug);
|
|
|
|
createProject(projectSlug);
|
|
waitForProjectPage(projectSlug);
|
|
|
|
// go to the development target
|
|
cy.get(`a[href="/${organizationSlug}/${projectSlug}/${targetSlug}"]`).click();
|
|
waitForTargetPage(targetSlug);
|
|
|
|
createRegistryAccessToken({ organizationSlug, projectSlug, targetSlug });
|
|
|
|
sendUsageReport({
|
|
report: {
|
|
size: 1,
|
|
map: {
|
|
op1: {
|
|
operation: 'query ping { ping }',
|
|
operationName: 'ping',
|
|
fields: ['Query', 'Query.ping'],
|
|
},
|
|
op2: {
|
|
operation: 'query pong { pong }',
|
|
operationName: 'pong',
|
|
fields: ['Query', 'Query.pong'],
|
|
},
|
|
},
|
|
operations: [
|
|
{
|
|
operationMapKey: 'op1',
|
|
timestamp: Date.now(),
|
|
execution: {
|
|
ok: true,
|
|
duration: 200_000_000,
|
|
errorsTotal: 0,
|
|
},
|
|
metadata: {
|
|
client: {
|
|
name: undefined,
|
|
version: 'vUndefined',
|
|
},
|
|
},
|
|
},
|
|
{
|
|
operationMapKey: 'op2',
|
|
timestamp: Date.now(),
|
|
execution: {
|
|
ok: true,
|
|
duration: 200_000_000,
|
|
errorsTotal: 0,
|
|
},
|
|
metadata: {
|
|
client: {
|
|
name: 'unknown',
|
|
version: 'vUnknown',
|
|
},
|
|
},
|
|
},
|
|
],
|
|
},
|
|
});
|
|
|
|
// visit Insights
|
|
cy.visit(`/${organizationSlug}/${projectSlug}/${targetSlug}/insights`);
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_ping');
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_pong');
|
|
// visit Insights of "unknown" client (we use "unknown" as a fallback for missing client name)
|
|
cy.visit(`/${organizationSlug}/${projectSlug}/${targetSlug}/insights/client/unknown`);
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_ping');
|
|
cy.get('h3').contains('Operations').parent().get('a').contains('_pong');
|
|
cy.get('h3').contains('Versions').parent().get('p').contains('vUndefined');
|
|
cy.get('h3').contains('Versions').parent().get('p').contains('vUnknown');
|
|
});
|
|
});
|