Skip to content

Commit 52fcf65

Browse files
authored
Merge pull request #272 from ioet/228-table-component
fix #272 table component on customer list
2 parents a77ac4f + 5e17dc8 commit 52fcf65

File tree

18 files changed

+2954
-2197
lines changed

18 files changed

+2954
-2197
lines changed

angular.json

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,22 @@
2424
"src/assets"
2525
],
2626
"styles": [
27+
"node_modules/datatables.net-dt/css/jquery.dataTables.css",
2728
"./node_modules/bootstrap/dist/css/bootstrap.min.css",
2829
"src/styles.scss",
29-
"node_modules/ngx-toastr/toastr.css"
30+
"node_modules/ngx-toastr/toastr.css",
31+
"node_modules/datatables.net-buttons-dt/css/buttons.dataTables.css"
3032
],
3133
"scripts": [
32-
"./node_modules/jquery/dist/jquery.min.js",
33-
"./node_modules/bootstrap/dist/js/bootstrap.min.js"
34+
"node_modules/jquery/dist/jquery.js",
35+
"./node_modules/bootstrap/dist/js/bootstrap.min.js",
36+
"node_modules/datatables.net/js/jquery.dataTables.js",
37+
"node_modules/jszip/dist/jszip.js",
38+
"node_modules/datatables.net-buttons/js/dataTables.buttons.js",
39+
"node_modules/datatables.net-buttons/js/buttons.colVis.js",
40+
"node_modules/datatables.net-buttons/js/buttons.flash.js",
41+
"node_modules/datatables.net-buttons/js/buttons.html5.js",
42+
"node_modules/datatables.net-buttons/js/buttons.print.js"
3443
]
3544
},
3645
"configurations": {

karma.conf.js

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,18 @@ module.exports = function (config) {
55
config.set({
66
basePath: '',
77
frameworks: ['jasmine', '@angular-devkit/build-angular'],
8+
files: [
9+
'node_modules/jquery/dist/jquery.js',
10+
'node_modules/datatables.net/js/jquery.dataTables.js',
11+
],
812
plugins: [
913
require('karma-jasmine'),
1014
require('karma-chrome-launcher'),
15+
require('@angular-devkit/build-angular/plugins/karma'),
1116
require('karma-jasmine-html-reporter'),
12-
require('karma-coverage-istanbul-reporter'),
13-
require('@angular-devkit/build-angular/plugins/karma')
17+
require('karma-spec-reporter'),
18+
require('karma-coverage-istanbul-reporter')
19+
1420
],
1521
client: {
1622
clearContext: false // leave Jasmine Spec Runner output visible in browser
@@ -26,7 +32,16 @@ module.exports = function (config) {
2632
functions: 80
2733
}
2834
},
29-
reporters: ['progress', 'kjhtml'],
35+
reporters: ['spec', 'kjhtml'],
36+
specReporter: {
37+
maxLogLines: 5,
38+
suppressErrorSummary: false,
39+
suppressFailed: false,
40+
suppressPassed: false,
41+
suppressSkipped: true,
42+
showSpecTiming: false
43+
},
44+
3045
port: 9876,
3146
colors: true,
3247
logLevel: config.LOG_INFO,

package-lock.json

Lines changed: 2673 additions & 2110 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,19 +23,31 @@
2323
"@ngrx/effects": "^9.0.0",
2424
"@ngrx/store": "^9.0.0",
2525
"@ngrx/store-devtools": "^9.0.0",
26+
"angular-datatables": "^9.0.2",
2627
"angular-ng-autocomplete": "^2.0.1",
2728
"bootstrap": "^4.4.1",
28-
"jquery": "^3.5.0",
29+
"datatables.net": "^1.10.21",
30+
"datatables.net-dt": "^1.10.21",
31+
"jquery": "^3.5.1",
2932
"minimist": "^1.2.5",
3033
"moment": "^2.25.3",
3134
"msal": "^1.2.1",
3235
"ngx-pagination": "^5.0.0",
3336
"ngx-toastr": "^12.0.1",
3437
"rxjs": "~6.5.4",
3538
"tslib": "^1.10.0",
36-
"zone.js": "~0.10.2"
39+
"zone.js": "~0.10.2",
40+
"jszip": "^3.4.0",
41+
"datatables.net-buttons": "^1.6.2",
42+
"datatables.net-buttons-dt": "^1.6.2",
43+
"@types/datatables.net-buttons": "^1.4.3"
3744
},
3845
"devDependencies": {
46+
"angular-ng-autocomplete": "^2.0.1",
47+
"angular-datatables": "^9.0.2",
48+
"jquery": "^3.5.1",
49+
"datatables.net": "^1.10.21",
50+
"datatables.net-dt": "^1.10.21",
3951
"@angular-devkit/build-angular": "^0.900.5",
4052
"@angular/cli": "~9.0.4",
4153
"@angular/compiler-cli": "~9.0.3",
@@ -47,14 +59,16 @@
4759
"@stryker-mutator/core": "^3.1.0",
4860
"@stryker-mutator/karma-runner": "^3.1.0",
4961
"@stryker-mutator/typescript": "^3.1.0",
62+
"@types/datatables.net": "^1.10.19",
5063
"@types/jasmine": "~3.5.0",
5164
"@types/jasminewd2": "~2.0.3",
65+
"@types/jquery": "^3.3.38",
5266
"@types/node": "^12.11.1",
5367
"codelyzer": "^5.1.2",
5468
"commit-message-validator": "^0.1.11",
5569
"husky": "^4.2.3",
5670
"jasmine-core": "~3.5.0",
57-
"jasmine-spec-reporter": "~4.2.1",
71+
"karma-spec-reporter": "^0.0.32",
5872
"karma": "^5.0.1",
5973
"karma-chrome-launcher": "~3.1.0",
6074
"karma-coverage-istanbul-reporter": "~2.1.0",

src/app/app.module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import { BrowserModule } from '@angular/platform-browser';
55
import { NgModule } from '@angular/core';
66
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
77
import { HttpClientModule, HTTP_INTERCEPTORS } from '@angular/common/http';
8+
import { DataTablesModule } from 'angular-datatables';
89
import { StoreModule } from '@ngrx/store';
910
import { EffectsModule } from '@ngrx/effects';
1011
import { StoreDevtoolsModule } from '@ngrx/store-devtools';
@@ -106,6 +107,7 @@ import { TimeDetailsPipe } from './modules/time-clock/pipes/time-details.pipe';
106107
ReactiveFormsModule,
107108
HttpClientModule,
108109
NgxPaginationModule,
110+
DataTablesModule,
109111
AutocompleteLibModule,
110112
StoreModule.forRoot(reducers, {
111113
metaReducers,
Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
<table class="table table-sm table-bordered table-striped mb-0">
1+
<table *ngIf="customers" class="table table-sm table-bordered table-striped mb-0" datatable [dtTrigger]="dtTrigger" [dtOptions]="dtOptions">
22
<thead class="thead-orange">
33
<tr class="d-flex">
44
<th class="col-9">Name</th>
5-
<th class="col-3 text-center"></th>
5+
<th class="col-3 text-center">Options</th>
66
</tr>
77
</thead>
88
<tbody>
99
<tr
1010
class="d-flex"
11-
*ngFor="let customer of customers | paginate: { itemsPerPage: itemsPerPage, currentPage: initPage1, id: 'first' }"
11+
*ngFor="let customer of customers"
1212
>
1313
<td class="col-sm-9">{{ customer.name }}</td>
1414
<td class="col-sm-3 text-center">
@@ -22,12 +22,3 @@
2222
</tr>
2323
</tbody>
2424
</table>
25-
<div class="d-flex align-items-end flex-column">
26-
<pagination-controls
27-
class="mt-auto p-2 custom-pagination"
28-
(pageChange)="initPage1 = $event"
29-
id="first"
30-
previousLabel=""
31-
nextLabel=""
32-
></pagination-controls>
33-
</div>
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +0,0 @@
1-
@import '../../../../../../../styles/colors.scss';
Lines changed: 87 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,64 @@
1-
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
2-
import { MockStore, provideMockStore } from '@ngrx/store/testing';
3-
4-
import { NgxPaginationModule } from 'ngx-pagination';
5-
import { CustomerListComponent } from './customer-list.component';
6-
import { allCustomers } from './../../../../store/customer-management.selectors';
7-
import { CustomerState, SetCustomerToEdit, DeleteCustomer } from 'src/app/modules/customer-management/store';
1+
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
2+
import {MockStore, provideMockStore} from '@ngrx/store/testing';
3+
4+
import {NgxPaginationModule} from 'ngx-pagination';
5+
import {CustomerListComponent} from './customer-list.component';
6+
import {
7+
CustomerManagementActionTypes,
8+
CustomerState,
9+
DeleteCustomer,
10+
LoadCustomers,
11+
SetCustomerToEdit
12+
} from 'src/app/modules/customer-management/store';
13+
import {DataTablesModule} from 'angular-datatables';
14+
import {ActionsSubject} from '@ngrx/store';
815

916
describe('CustomerTableListComponent', () => {
1017
let component: CustomerListComponent;
1118
let fixture: ComponentFixture<CustomerListComponent>;
1219
let store: MockStore<CustomerState>;
13-
let mockCustomerSelector;
20+
const actionSub: ActionsSubject = new ActionsSubject();
1421

1522
const state = {
16-
data: [{ tenant_id: 'id', name: 'name', description: 'description' }],
23+
data: [{tenant_id: 'id', name: 'name', description: 'description'}],
1724
isLoading: false,
1825
message: '',
1926
customerIdToEdit: '',
2027
customerId: ''
2128
};
2229

2330

24-
2531
beforeEach(async(() => {
2632
TestBed.configureTestingModule({
27-
imports: [NgxPaginationModule],
33+
imports: [NgxPaginationModule, DataTablesModule],
2834
declarations: [CustomerListComponent],
2935
providers: [
30-
provideMockStore({ initialState: state })
36+
provideMockStore({initialState: state}),
37+
{provide: ActionsSubject, useValue: actionSub}
3138
],
3239
}).compileComponents();
3340
}));
3441

3542
beforeEach(() => {
3643
fixture = TestBed.createComponent(CustomerListComponent);
3744
component = fixture.componentInstance;
38-
fixture.detectChanges();
3945

4046
store = TestBed.inject(MockStore);
4147
store.setState(state);
42-
mockCustomerSelector = store.overrideSelector(allCustomers, state.data);
48+
fixture.detectChanges();
49+
4350
});
4451

4552
it('component should be created', () => {
4653
expect(component).toBeTruthy();
4754
});
4855

49-
it('onNgInit customers are loaded from store executing an action', () => {
56+
it('when the component is initialized the load customer action is triggered', () => {
5057
spyOn(store, 'dispatch');
5158

5259
component.ngOnInit();
5360

54-
expect(store.dispatch).toHaveBeenCalled();
55-
expect(component.customers).toEqual(state.data);
61+
expect(store.dispatch).toHaveBeenCalledWith(new LoadCustomers());
5662
});
5763

5864
it('onClick edit, dispatch SetCustomerToEdit and enable customer form', () => {
@@ -72,7 +78,71 @@ describe('CustomerTableListComponent', () => {
7278
expect(store.dispatch).toHaveBeenCalledWith(new DeleteCustomer('1'));
7379
});
7480

81+
const params = [
82+
{actionName: 'delete', actionType: CustomerManagementActionTypes.DELETE_CUSTOMER_SUCCESS},
83+
{actionName: 'update', actionType: CustomerManagementActionTypes.UPDATE_CUSTOMER_SUCCESS},
84+
{actionName: 'create', actionType: CustomerManagementActionTypes.CREATE_CUSTOMER_SUCCESS}
85+
];
86+
87+
params.map(param =>
88+
it(`on success ${param.actionName} customer, the load all customer action should be triggered`, () => {
89+
const actionSubject = TestBed.get(ActionsSubject) as ActionsSubject;
90+
const action = {
91+
type: param.actionType
92+
};
93+
spyOn(store, 'dispatch');
94+
95+
actionSubject.next(action);
96+
97+
expect(store.dispatch).toHaveBeenCalledWith(new LoadCustomers());
98+
}));
99+
100+
params.map(param =>
101+
it(`on success ${param.actionName} customer, the customer form should be disabled`, () => {
102+
const actionSubject = TestBed.get(ActionsSubject) as ActionsSubject;
103+
const action = {
104+
type: param.actionType
105+
};
106+
actionSubject.next(action);
107+
108+
expect(component.showCustomerForm).toBe(false);
109+
}));
110+
111+
it('on success load customers, the customer list should be populated', () => {
112+
const actionSubject = TestBed.get(ActionsSubject) as ActionsSubject;
113+
const action = {
114+
type: CustomerManagementActionTypes.LOAD_CUSTOMERS_SUCCESS,
115+
payload: state.data
116+
};
117+
118+
actionSubject.next(action);
119+
120+
expect(component.customers).toEqual(state.data);
121+
});
122+
123+
// it('on success load customer and the datatable was already initialized, then the datatable should be destroyed ' +
124+
// 'before reloading the customer data', () => {
125+
// const actionSubject = TestBed.get(ActionsSubject) as ActionsSubject;
126+
// component.isDtInitialized = true;
127+
// const action = {
128+
// type: CustomerManagementActionTypes.LOAD_CUSTOMERS_SUCCESS,
129+
// payload: state.data
130+
// };
131+
// const dtApi: DataTables.Api = jasmine.createSpyObj<DataTables.Api>('dtApi', ['destroy']);
132+
// component.dtElement.dtInstance = Promise.resolve(dtApi);
133+
// spyOn(component.dtElement.dtInstance, 'then');
134+
//
135+
// actionSubject.next(action);
136+
//
137+
// expect(component.dtElement.dtInstance.then).toHaveBeenCalled();
138+
// // TODO Improve this test. This is not testing the datatable is destroyed
139+
// // expect(dtApi.destroy).toHaveBeenCalled();
140+
// });
141+
75142
afterEach(() => {
143+
component.dtTrigger.unsubscribe();
144+
component.changeCustomerSubscription.unsubscribe();
145+
component.loadCustomersSubscription.unsubscribe();
76146
fixture.destroy();
77147
});
78148
});

0 commit comments

Comments
 (0)