Skip to content

Commit

Permalink
Merge pull request #649 from RedHatInsights/devel
Browse files Browse the repository at this point in the history
Release 2021/11/02
  • Loading branch information
skochay330 authored Nov 2, 2021
2 parents ddbe6cb + d2a4f81 commit 62e0326
Show file tree
Hide file tree
Showing 88 changed files with 8,593 additions and 7,003 deletions.
15 changes: 10 additions & 5 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
FROM node:15
FROM registry.access.redhat.com/ubi8/nodejs-14

WORKDIR /app
COPY package.json /app
COPY package-lock.json /app
USER 0
RUN curl -sL https://rpm.nodesource.com/setup_16.x | bash -
RUN yum remove -y nodejs npm
RUN yum install -y nodejs
RUN yum install -y bzip2 fontconfig nss.x86_64 pango.x86_64 libXcomposite.x86_64 libXcursor.x86_64 libXdamage.x86_64 libXext.x86_64 libXi.x86_64 libXtst.x86_64 cups-libs.x86_64 libXScrnSaver.x86_64 libXrandr.x86_64 GConf2.x86_64 alsa-lib.x86_64 atk.x86_64 gtk3.x86_64 libdrm libgbm libxshmfence

WORKDIR /src
COPY . /src
RUN npm ci
COPY . /app

CMD npm run start:container
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,18 @@ Automation Analytics provides data analytics for Ansible Tower that provides vis
3. `npm start` - starts standalone: webpack serves the files alongside with insights, rbac and keycloak.
4. Go to `http://localhost:1337/beta/ansible/insights` and use the admin/admin credentials to login.

#### Developing against a deployed backend

1. `npm ci` - install dependencies from the lockfile
2. `npm start --env=stage` - starts local frontend while proxying all the request to the stage environment.
3. Follow the link the proxy outputs to the terminal - this is different from env to env. You need valid credentials for the environment you are running against to be able to log in

#### WIP: Developing against a backend on the ephemeral (ephemeral is not supporting it yet)

1. `npm ci` - install dependencies from the lockfile
2. `npm start --env=eph --eph_id=YOUR_EPH_ID` - starts local frontend while proxying all the request to the eph environment.
3. Follow the link the proxy outputs to the terminal - this is different from env to env. You need valid credentials for the environment you are running against to be able to log in

### Testing

- `npm run lint` - runs eslint
Expand Down
23 changes: 23 additions & 0 deletions build_deploy.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash

# --------------------------------------------
# Export vars for helper scripts to use
# --------------------------------------------
# name of app-sre "application" folder this component lives in; needs to match for quay
export COMPONENT="tower-analytics"
export APP_NAME=`node -e 'console.log(require("./package.json").insights.appname)'` # `automation-analytics`
export IMAGE="quay.io/cloudservices/automation-analytics-frontend"
export APP_ROOT=$(pwd)
cat /etc/redhat-release
COMMON_BUILDER=https://raw.githubusercontent.com/RedHatInsights/insights-frontend-builder-common/master

set -exv

npm ci
npm run verify

# Generate nginx config based on app name in package.json
curl -sSL $COMMON_BUILDER/src/nginx_conf_gen.sh | bash -s

curl -sSL $COMMON_BUILDER/src/quay_push.sh | bash -s

65 changes: 47 additions & 18 deletions config/dev.webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,58 @@ const {
defaultServices,
} = require('@redhat-cloud-services/frontend-components-config-utilities/standalone');

// TODO: Add 'prod' - currently it is not wokring while returns
// errors on backend queries: strict cross origin policy
const validEnvValues = ['standalone', 'stage', 'eph'];

const env = validEnvValues.includes(process.env.npm_config_env)
? process.env.npm_config_env
: 'standalone';

// Only when using ephemeral environment
const ephId = process.env.npm_config_eph_id ?? '1';

const environmentSetup = {
...(env === 'standalone' && {
https: false,
standalone: {
apiAnalytics: {
context: ['/api/tower-analytics'],
target: 'http://localhost:8004',
},
rbac,
...defaultServices,
},
registry: [
({ app }) =>
app.get('(/beta)?/config/chrome/ansible-navigation.json', (_req, res) =>
res.sendFile(resolve(__dirname, './ansible-navigation.json'))
),
],
}),
...(['prod', 'stage'].includes(env) && {
https: true,
useProxy: true,
proxyVerbose: true,
env: `${env}-beta`,
}),
...(['eph'].includes(env) && {
https: true,
useProxy: true,
proxyVerbose: true,
env: 'qa-beta', // TODO change to whatewer the aggregator pulls data from
keycloakUri: `https://keycloak-ephemeral-${ephId}.apps.c-rh-c-eph.8p0c.p1.openshiftapps.com`,
target: `https://front-end-aggregator-ephemeral-${ephId}.apps.c-rh-c-eph.8p0c.p1.openshiftapps.com`,
}),
};

const { config: webpackConfig, plugins } = config({
rootFolder: resolve(__dirname, '../'),
debug: true,
sassPrefix: '.automation-analytics, .automationAnalytics',
useCloud: true,
https: false,
standalone: {
apiAnalytics: {
context: ['/api/tower-analytics'],
target: 'http://localhost:8004',
},
rbac,
...defaultServices,
},
registry: [
({ app }) =>
app.get('(/beta)?/config/chrome/ansible-navigation.json', (_req, res) =>
res.sendFile(resolve(__dirname, './ansible-navigation.json'))
),
],
appUrl: ['/beta/ansible/insights/', '/ansible/insights/'],
proxyVerbose: true,
...(process.env.BETA && { deployment: 'beta/apps' }),
deployment: 'beta/apps',
...environmentSetup,
});

plugins.push(
Expand Down
9 changes: 1 addition & 8 deletions cypress/integration/AutomationCalculator.spec.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* global cy */
import { appid, calculatorUrl, jobExplorerUrl } from '../support/constants';
import { appid, calculatorUrl } from '../support/constants';

describe('Automation Caluclator page smoketests', () => {
beforeEach(() => {
Expand Down Expand Up @@ -31,14 +31,7 @@ describe('Automation Caluclator page smoketests', () => {
}
});

xit('can click on the template name', () => {
cy.get('.top-templates').find('a').eq(0).click();
cy.location().should((location) => {
expect(location.pathname).to.include(jobExplorerUrl);
});
});
it('Query parameters are stored in the URL to enable refresh', () => {
// Add more once fixtures are implemented - other filters are content-dependent.
cy.get('[data-cy="quick_date_range"]').click();
cy.contains('Past 2 years').click();
cy.url().should('include', 'quick_date_range=roi_last_2_years');
Expand Down
92 changes: 34 additions & 58 deletions cypress/integration/Dashboard.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ const appid = Cypress.env('appid');

// const toolBarCatSelector =
// 'div[id="filterable-toolbar-with-chip-groups"] > .pf-c-toolbar__content > .pf-c-toolbar__content-section > div[class="pf-c-toolbar__group pf-m-filter-group"]';
const toolBarChipGroup =
'#filterable-toolbar-with-chip-groups > div:nth-child(2)';
const toolBarChipGroup = '.pf-c-chip-group';

const setDate = (input, value) => {
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(
Expand All @@ -24,32 +23,37 @@ async function fuzzClustersPage() {
// open each top template modal and save a screenshot ...
for (let i = 0; i <= 4; i++) {
cy.get(appid)
.find('a')
.find('a', { timeout: 6000 })
.eq(i)
.click({ waitForAnimations: true })
.click()
.then(() => {
cy.screenshot('top-template-modal-' + i + '.png', {
capture: 'fullPage',
});
});
cy.get('[aria-label="Close"]').click();
}

// navigate to the job explorer page for each bar in the chart ...
for (let i = 0; i <= 4; i++) {
// pick a random bar to click on ...
const barid = parseInt(Math.floor(Math.random() * 10));
// navigate to the job explorer page for each bar in the chart ...
for (let i = 0; i <= 4; i++) {
// pick a random bar to click on ...
const barid = parseInt(Math.floor(Math.random() * 10));

// click it and wait for the jobexplorer page to load ...
cy.get(appid)
.find('#d3-bar-chart-root', { timeout: 1000 })
.should('be.visible');
cy.get(appid).find('rect').eq(barid).click({ waitForAnimations: true });
cy.screenshot('clusters-bar-' + barid + '-jobexplorer-details.png', {
capture: 'fullPage',
});
// click it and wait for the jobexplorer page to load ...
cy.get(appid)
.find('#d3-bar-chart-root', { timeout: 6000 })
.should('be.visible');
cy.get(appid)
.find('rect')
.eq(barid)
.click({ force: true, waitForAnimations: true });
cy.url().should('include', 'job-explorer');
cy.screenshot('clusters-bar-' + barid + '-jobexplorer-details.png', {
capture: 'fullPage',
});

// go back to the clusters page ...
cy.visit(dashboardUrl);
}
// go back to the clusters page ...
cy.visit(dashboardUrl);
}
}

Expand All @@ -63,17 +67,6 @@ describe('Dashboard page smoketests', () => {
fuzzClustersPage();
});

xit('Page contains chart, and 3 card elements', () => {
cy.get('#d3-bar-chart-root').should((chartElem) => {
expect(chartElem).to.have.length(1);
});

// fails due to bug: https://issues.redhat.com/browse/AA-470
it.skip('can interact with the clusters page without breaking the UI', () => {
fuzzClustersPage();
});
});

it('Page contains chart, and 3 card elements', () => {
cy.get('#d3-bar-chart-root').should((chartElem) => {
expect(chartElem).to.have.length(1);
Expand All @@ -84,20 +77,18 @@ describe('Dashboard page smoketests', () => {
});

it('There is a filter toolbar on the Clusters page', () => {
cy.get('div[id="filterable-toolbar-with-chip-groups"]').should(
(toolbar) => {
expect(toolbar).to.have.length(1);
}
);
cy.get('.pf-c-toolbar__content-section').should((toolbar) => {
expect(toolbar).to.have.length(1);
});
});
});


describe('Dashboard page filter tests', () => {
beforeEach(() => {
cy.loginFlow();
cy.visit(dashboardUrl);
});

it('Can filter by organization', () => {
cy.get('button[class="pf-c-select__toggle"]').eq(0).click();
cy.get('button[class*="pf-c-select__menu-item"]')
Expand All @@ -124,7 +115,6 @@ describe('Dashboard page filter tests', () => {
const screenshotFilename = 'clusters_filter_by_org.png';
cy.screenshot(screenshotFilename);
});

it('Can filter by a preset date range', () => {
const todayminusone = moment(new Date().toISOString())
.subtract(1, 'day')
Expand Down Expand Up @@ -297,7 +287,7 @@ describe('Dashboard page filter tests', () => {
});

it('Can clear filters', () => {
cy.get('button[class="pf-c-select__toggle"]').eq(0).click();
cy.get('button[class="pf-c-select__toggle"]', { timeout: 6000 }).eq(0).click();
cy.get('button[class*="pf-c-select__menu-item"]')
.contains('Organization')
.click();
Expand All @@ -311,18 +301,18 @@ describe('Dashboard page filter tests', () => {
.contains('No organization')
.parent()
.siblings('input')
.click();
.click()
.type('{esc}');
// Verify the filter is added in the Chip group
cy.get(toolBarChipGroup)
.find('span')
.contains('Organization')
.siblings()
.find('span')
.contains('No organization');
cy.get(toolBarChipGroup)
.find('button')
.contains('Clear all filters')
.click();
cy.get(
'#pf-random-id-0 > :nth-child(2) > :nth-child(2) > .pf-c-button'
).click();
// Verify the filter is removed from the Chip group
cy.get(toolBarChipGroup).find('span').should('not.contain', 'Organization');
const screenshotFilename = 'clusters_clear_filter.png';
Expand Down Expand Up @@ -377,8 +367,7 @@ describe('Dashboard page drilldown tests', () => {
cy.screenshot(screenshotFilename);
});

// will fail due to bug: https://issues.redhat.com/browse/AA-534 and https://issues.redhat.com/browse/AA-535
it.skip('Can navigate to job explorer from top templates modal', () => {
it('Can navigate to job explorer from top templates modal', () => {
const todayminusone = moment(new Date().toISOString())
.subtract(1, 'day')
.format('M/D');
Expand Down Expand Up @@ -430,21 +419,8 @@ describe('Dashboard page drilldown tests', () => {
cy.get('#pf-modal-part-0').find('a').contains('View all jobs').click();
// Verify the redirect to Job explorer
cy.get(appid).find('.pf-c-title').contains('Job Explorer');
// Verify the organization and date range filter is carried correctly to Job Explorer page
cy.get(toolBarChipGroup)
.find('span')
.contains('Organization')
.siblings()
.find('span')
.contains('No organization');
cy.get('div[data-cy="quick_date_range"]').contains('Past 62 days');
cy.get(toolBarChipGroup).find('span').contains('Template');
cy.get(toolBarChipGroup)
.find('span')
.contains('Job')
.siblings()
.find('span')
.should('not.contain', 'Playbook run');
const screenshotFilename = 'clusters_drilldown_top_templates.png';
cy.screenshot(screenshotFilename);
});
Expand Down
22 changes: 15 additions & 7 deletions cypress/integration/Global.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,23 @@ describe('Insights smoketests', () => {
cy.loginFlow();
});

xit('has all the AA navigation items', () => {
cy.visit('/ansible/automation-analytics');
const navbar = cy.get('li[ouiaid="automation-analytics"]');
const navlis = navbar.find('li');
navlis.should('have.length', 5);
it('has all the AA navigation items', () => {
cy.visit(dashboardUrl);
cy.get('[aria-labelledby="Operations Insights"]')
.find('.pf-c-nav__toggle-icon')
.click({ multiple: true });
cy.get('[aria-labelledby="Operations Insights"]')
.find('li')
.should('have.length', 11);
cy.get('[aria-labelledby="Security Insights"]')
.find('li')
.should('have.length', 1);
cy.get('[aria-labelledby="Business Insights"]')
.find('li')
.should('have.length', 6);
});

// requires expansion
it('can open each page without breaking the UI', () => {
cy.visit('/ansible/automation-analytics');
cy.visit(calculatorUrl);
cy.visit(jobExplorerUrl);
cy.visit(dashboardUrl);
Expand Down
Loading

0 comments on commit 62e0326

Please sign in to comment.