Skip to content

Commit

Permalink
7346 - Adding "no target found." message to targets (#7377)
Browse files Browse the repository at this point in the history
Ticket: #7346

This commit adds a message for when an user doesn't have targets in the view.
  • Loading branch information
latin-panda committed Nov 2, 2021
1 parent c50dd5e commit 81a95db
Show file tree
Hide file tree
Showing 6 changed files with 193 additions and 5 deletions.
Expand Up @@ -1245,6 +1245,7 @@ targets.disabled = Targets are disabled for your user account.
targets.facility_deliveries.title = Deliveries at facility
targets.homebirth_1_visit.title = Homebirths with 1+ PNC visit
targets.homebirth_no_visits.title = Homebirths with 0 PNC visits
targets.no_targets = No target found.
targets.past_3mos.subtitle = Past 3 months
targets.pnc_registrations.title = PNC registrations
targets.pnc_visits.title = PNC visits
Expand Down
109 changes: 109 additions & 0 deletions tests/e2e/analytics/analytics.wdio-spec.js
@@ -0,0 +1,109 @@
const path = require('path');
const expect = require('chai').expect;

const utils = require('../../utils');
const sentinelUtils = require('../sentinel/utils');
const analyticsPage = require('../../page-objects/analytics/analytics.wdio.page');
const loginPage = require('../../page-objects/login/login.wdio.page');
const commonPage = require('../../page-objects/common/common.wdio.page');
const chtConfUtils = require('../../cht-conf-utils');

const contacts = [
{
_id: 'fixture:district',
type: 'district_hospital',
name: 'District',
place_id: 'district',
reported_date: new Date().getTime(),
},
{
_id: 'fixture:center',
type: 'health_center',
name: 'Health Center',
parent: { _id: 'fixture:district' },
place_id: 'health_center',
reported_date: new Date().getTime(),
},
];

const chw = {
username: 'bob',
password: 'medic.123',
place: 'fixture:center',
contact: { _id: 'fixture:user:bob', name: 'Bob' },
roles: [ 'chw' ],
};

const updateSettings = async (settings) => {
await utils.updateSettings(settings, 'api');
await commonPage.sync(true);
await browser.refresh();
};

const compileTargets = async (configDirectory) => {
await chtConfUtils.initializeConfigDir();
const targetFilePath = path.join(__dirname, configDirectory, 'targets.js');

return chtConfUtils.compileNoolsConfig({ targets: targetFilePath });
};

describe('Targets', () => {
before(async () => {
await utils.saveDocs(contacts);
await utils.createUsers([ chw ]);
await sentinelUtils.waitForSentinel();

await loginPage.login({ username: chw.username, password: chw.password });
await commonPage.closeTour();
await (await commonPage.analyticsTab()).waitForDisplayed();
});

afterEach(async () => {
await utils.revertSettings(true);
});

it('should display targets from default config', async () => {
await analyticsPage.goToTargets();

const targets = await analyticsPage.getTargets();

expect(targets).to.have.deep.members([
{ title: 'Deaths', goal: '0', count: '0' },
{ title: 'New pregnancies', goal: '20', count: '0' },
{ title: 'Live births', count: '1' }, // This is CHW Bob, the target counts any contact type 'person'.
{ title: 'Active pregnancies', count: '0' },
{ title: 'Active pregnancies with 1+ routine facility visits', count: '0' },
{ title: 'In-facility deliveries', percent: '0%', percentCount: '(0 of 0)' },
{ title: 'Active pregnancies with 4+ routine facility visits', count: '0' },
{ title: 'Active pregnancies with 8+ routine contacts', count: '0' },
]);
});

it('should display correct message when no target found', async () => {
const settings = await compileTargets('no-targets-config');
await updateSettings(settings);
await analyticsPage.goToTargets();

const emptySelection = await analyticsPage.noSelectedTarget();
await (emptySelection).waitForDisplayed();
await commonPage.waitForLoaderToDisappear(emptySelection);

expect(await emptySelection.getText()).to.equal('No target found.');
});

it('should display correct message when targets are disabled', async () => {
const tasks = {
targets: { enabled: false }
};
await updateSettings({ tasks });
await analyticsPage.goToTargets();

const emptySelection = await analyticsPage.noSelectedTarget();
await (emptySelection).waitForDisplayed();
await commonPage.waitForLoaderToDisappear(emptySelection);

expect(await emptySelection.getText()).to.equal(
'Targets are disabled for admin users. If you need to see targets, login as a normal user.'
);
});
});
9 changes: 9 additions & 0 deletions tests/e2e/analytics/no-targets-config/targets.js
@@ -0,0 +1,9 @@
module.exports = [
{
id: 'deaths-this-month',
context: 'user.parent.type === "district_hospital"',
type: 'count',
goal: 0,
appliesTo: 'contacts'
},
];
61 changes: 61 additions & 0 deletions tests/page-objects/analytics/analytics.wdio.page.js
@@ -0,0 +1,61 @@
const goToTargets = () => browser.url('/#/analytics/targets');

const noSelectedTarget = () => $('.empty-selection');

const targets = () => $$('.target');

const targetWrap = () => $('.page .targets');

const targetTitle = (targetElement) => targetElement.$('.heading .title h2');

const targetGoal = (targetElement) => targetElement.$('.body .count .goal');

const targetCountNumber = (targetElement) => targetElement.$('.body .count .number');

const targetProgressNumber = (targetElement) => targetElement.$('.body .target-progress .number');

const targetNumberPercent = (targetElement) => targetElement.$('.body .target-progress .number .value');

const targetNumberPercentCount = (targetElement) => targetElement.$('.body .target-progress .number span:nth-child(2)');

const targetGoalValue = (targetElement) => targetElement.$('.body .count .goal p');

const getTargetInfo = async (targetElement) => {
const target = {
title: await (await targetTitle(targetElement)).getText()
};

if (await (await targetGoal(targetElement)).isExisting()) {
target.goal = await (await targetGoalValue(targetElement)).getText();
}

if (await (await targetCountNumber(targetElement)).isExisting()) {
target.count = await (await targetCountNumber(targetElement)).getText();
}

if (await (await targetProgressNumber(targetElement)).isExisting()) {
target.percent = await (await targetNumberPercent(targetElement)).getText();
target.percentCount = await (await targetNumberPercentCount(targetElement)).getText();
}

return target;
};

const getTargets = async () => {
await (await targetWrap()).waitForDisplayed();
const displayedTargets = await targets();

const targetList = [];
for (const target of displayedTargets) {
const info = await getTargetInfo(target);
targetList.push(info);
}

return targetList;
};

module.exports = {
noSelectedTarget,
goToTargets,
getTargets,
};
14 changes: 9 additions & 5 deletions webapp/src/ts/modules/analytics/analytics-targets.component.html
@@ -1,31 +1,35 @@
<div class="page scrolling">
<div class="item-content empty-selection" *ngIf="targetsDisabled">
<div>{{'targets.disabled' | translate}}</div>
<div>{{ 'targets.disabled' | translate }}</div>
</div>

<div class="item-content empty-selection" *ngIf="!targetsDisabled && loading">
<div><div class="loader"></div></div>
</div>

<div class="targets" *ngIf="!targetsDisabled && !loading">
<div class="item-content empty-selection" *ngIf="!targetsDisabled && !loading && !targets?.length">
<div>{{ 'targets.no_targets' | translate }}</div>
</div>

<div class="targets" *ngIf="!targetsDisabled && !loading && targets?.length">
<div class="target"
*ngFor="let target of targets"
[ngClass]="{ 'has-goal': target.goal >= 0, 'goal-met': (target.value?.pass >= target.goal) || (target.value?.percent >= target.goal) }"
attr.test-target-id="{{ target.id }}">
<div class="heading">
<div class="icon" [innerHTML]="target.icon | resourceIcon"></div>
<div class="title">
<h2 *ngIf="target.translation_key">{{ target.translation_key | translate}}</h2>
<h2 *ngIf="target.translation_key">{{ target.translation_key | translate }}</h2>
<h2 *ngIf="!target.translation_key">{{ target.name | translateFrom }}</h2>
<p *ngIf="target.subtitle_translation_key">{{ target.subtitle_translation_key | translate}}</p>
<p *ngIf="target.subtitle_translation_key">{{ target.subtitle_translation_key | translate }}</p>
</div>
</div>

<div class="body">
<mm-analytics-targets-progress *ngIf="target.type === 'percent'" [target]="target" [value]="target.value" [aggregate]="false"></mm-analytics-targets-progress>
<div class="count" *ngIf="target.type !== 'percent'">
<div class="goal" *ngIf="target.goal >= 0">
<label>{{'analytics.target.monthly_goal' | translate}}</label>
<label>{{ 'analytics.target.monthly_goal' | translate }}</label>
<p>{{ target.goal | localizeNumber }}</p>
</div>
<div class="number">{{ target.value?.pass | localizeNumber }}</div>
Expand Down
@@ -1,4 +1,5 @@
import { ComponentFixture, fakeAsync, TestBed, tick, waitForAsync } from '@angular/core/testing';
import { TranslateFakeLoader, TranslateLoader, TranslateModule } from '@ngx-translate/core';
import sinon from 'sinon';
import { expect } from 'chai';

Expand All @@ -22,6 +23,9 @@ describe('AnalyticsTargetsComponent', () => {
return TestBed
.configureTestingModule({
declarations: [ AnalyticsTargetsComponent ],
imports: [
TranslateModule.forRoot({ loader: { provide: TranslateLoader, useClass: TranslateFakeLoader } }),
],
providers: [
{ provide: RulesEngineService, useValue: rulesEngineService },
{ provide: TelemetryService, useValue: telemetryService }
Expand Down

0 comments on commit 81a95db

Please sign in to comment.