Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CXSPA-3073: RxJs 7 #17362

Merged
merged 9 commits into from
May 8, 2023
9 changes: 2 additions & 7 deletions docs/libs/creating-lib.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,20 +60,15 @@ Just copy paste the following and and make sure to rename `TODO:` to you lib's n
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['parallel', 'jasmine', '@angular-devkit/build-angular'],
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-parallel'),
require('karma-jasmine'),
require('karma-coverage'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('@angular-devkit/build-angular/plugins/karma'),
require('karma-junit-reporter'),
],
parallelOptions: {
executors: 2,
shardStrategy: 'round-robin',
},
client: {
clearContext: false, // leave Jasmine Spec Runner output visible in browser
},
Expand Down Expand Up @@ -207,7 +202,7 @@ Use the following template:
"peerDependencies": {
"@angular/common": "^10.1.0",
"@angular/core": "^10.1.0",
"rxjs": "^6.6.0",
"rxjs": "^7.8.0",
"@spartacus/core": "3.0.0-next.0",
"@spartacus/storefront": "3.0.0-next.0"
}
Expand Down
7 changes: 1 addition & 6 deletions feature-libs/asm/karma.conf.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,15 @@
module.exports = function (config) {
config.set({
basePath: '',
frameworks: ['parallel', 'jasmine', '@angular-devkit/build-angular'],
frameworks: ['jasmine', '@angular-devkit/build-angular'],
plugins: [
require('karma-parallel'),
require('karma-jasmine'),
require('karma-coverage'),
require('karma-chrome-launcher'),
require('karma-jasmine-html-reporter'),
require('@angular-devkit/build-angular/plugins/karma'),
require('karma-junit-reporter'),
],
parallelOptions: {
executors: 2,
shardStrategy: 'round-robin',
},
client: {
clearContext: false, // leave Jasmine Spec Runner output visible in browser
jasmine: {
Expand Down
2 changes: 1 addition & 1 deletion feature-libs/asm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
"@spartacus/storefront": "5.0.0",
"@spartacus/styles": "5.0.0",
"@spartacus/user": "5.0.0",
"rxjs": "^6.6.0"
"rxjs": "^7.8.0"
},
"publishConfig": {
"access": "public"
Expand Down
4 changes: 2 additions & 2 deletions feature-libs/cart/base/core/facade/multi-cart.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
OrderEntry,
} from '@spartacus/cart/base/root';
import { isNotUndefined, StateUtils, UserIdService } from '@spartacus/core';
import { EMPTY, Observable, timer } from 'rxjs';
import { Observable, of, timer } from 'rxjs';
import {
debounce,
distinctUntilChanged,
Expand Down Expand Up @@ -76,7 +76,7 @@ export class MultiCartService implements MultiCartFacade {
// This flickering should only be avoided when switching from false to true
// Start of loading should be showed instantly (no debounce)
// Extra actions are only dispatched after some loading
debounce((isStable) => (isStable ? timer(0) : EMPTY)),
debounce((isStable) => (isStable ? timer(0) : of(undefined))),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why we change it?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

distinctUntilChanged()
);
}
Expand Down
2 changes: 1 addition & 1 deletion feature-libs/cart/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
"@spartacus/styles": "5.0.0",
"@spartacus/user": "5.0.0",
"bootstrap": "^4.6.2",
"rxjs": "^6.6.0"
"rxjs": "^7.8.0"
},
"publishConfig": {
"access": "public"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import {
QueryState,
UserIdService,
} from '@spartacus/core';
import { of } from 'rxjs';
import { config, of } from 'rxjs';
import { take } from 'rxjs/operators';
import { CheckoutDeliveryAddressConnector } from '../connectors/checkout-delivery-address/checkout-delivery-address.connector';
import { CheckoutDeliveryAddressService } from './checkout-delivery-address.service';
Expand Down Expand Up @@ -55,6 +55,9 @@ class MockCheckoutQueryFacade implements Partial<CheckoutQueryFacade> {
);
}

// configure rxjs to not crash node instance with thrown errors
config.onUnhandledError = (err) => console.warn(err);

describe(`CheckoutDeliveryAddressService`, () => {
let service: CheckoutDeliveryAddressService;
let connector: CheckoutDeliveryAddressConnector;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ export class OccCheckoutDeliveryModesAdapter
backOff({
shouldRetry: isJaloError,
}),
map((listResponse) => listResponse.deliveryModes),
map((modes) => modes ?? []),
map((listResponse) => listResponse.deliveryModes ?? []),
this.converter.pipeableMany(DELIVERY_MODE_NORMALIZER)
);
}
Expand Down
2 changes: 1 addition & 1 deletion feature-libs/checkout/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
"@spartacus/styles": "5.0.0",
"@spartacus/user": "5.0.0",
"bootstrap": "^4.6.2",
"rxjs": "^6.6.0"
"rxjs": "^7.8.0"
},
"publishConfig": {
"access": "public"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import { ComponentFixture, TestBed } from '@angular/core/testing';
import { EventService, I18nTestingModule } from '@spartacus/core';
import {
CustomerTicketingConfig,
CustomerTicketingFacade,
STATUS_NAME,
TicketDetails,
TicketEvent,
} from '@spartacus/customer-ticketing/root';
import { MessageEvent } from '@spartacus/storefront';
import { BehaviorSubject, EMPTY } from 'rxjs';
import { CustomerTicketingMessagesComponent } from './customer-ticketing-messages.component';
import createSpy = jasmine.createSpy;
Expand All @@ -21,12 +25,13 @@ describe('CustomerTicketMessagesComponent', () => {
const mockResponse = { message: mockSendEvent.message, code: 'mockCode' };

const createTicketResponse$ = new BehaviorSubject<TicketEvent>({});
const getTicket$ = new BehaviorSubject<TicketDetails>({});

class MockCustomerTicketingFacade
implements Partial<CustomerTicketingFacade>
{
createTicketEvent = () => createTicketResponse$;
getTicket = createSpy().and.returnValue(EMPTY);
getTicket = createSpy().and.returnValue(getTicket$.asObservable());
downloadAttachment = createSpy().and.returnValue(EMPTY);
uploadAttachment = createSpy().and.returnValue(EMPTY);
}
Expand Down Expand Up @@ -119,4 +124,60 @@ describe('CustomerTicketMessagesComponent', () => {
'mockId'
);
});

describe('messaging', () => {
let mockTicketDetails: TicketDetails;

beforeEach(() => {
mockTicketDetails = {
ticketEvents: [
{
createdAt: 'mock-create-date',
author: 'mock-author',
message: 'mock-message',
addedByAgent: true,
ticketEventAttachments: [{}],
},
],
status: { id: 'mock-status-id', name: STATUS_NAME.OPEN },
};

getTicket$.next(mockTicketDetails);
});

it('should provide the ticket events as messages', () => {
const expected: MessageEvent[] = [
{
createdAt: 'mock-create-date',
author: 'mock-author',
message: 'mock-message',
addedByAgent: true,
ticketEventAttachments: [{}],
text: 'mock-message',
rightAlign: true,
attachments: [{}],
} as MessageEvent & { message: string },
];

component.messageEvents$.subscribe((actual) => {
expect(actual).toEqual(expected);
});
});

it('should generate a messages config', () => {
const customerTicketingConfig = TestBed.inject(CustomerTicketingConfig);
const actual = component.messagingConfigs;

actual.displayAddMessageSection?.subscribe((displayAddMessageSection) =>
expect(displayAddMessageSection).toBe(true)
);
expect(actual.attachmentRestrictions).toEqual(
customerTicketingConfig.customerTicketing?.attachmentRestrictions
);
expect(actual.charactersLimit).toEqual(
customerTicketingConfig.customerTicketing?.inputCharactersLimit
);
expect(actual.enableFileUploadOption).toBe(true);
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ import {
CustomerTicketingFacade,
STATUS,
STATUS_NAME,
TicketEvent,
} from '@spartacus/customer-ticketing/root';
import { LaunchDialogService } from '@spartacus/storefront';
import { EMPTY } from 'rxjs';
import { EMPTY, of } from 'rxjs';
import { CustomerTicketingReopenDialogComponent } from './customer-ticketing-reopen-dialog.component';
import createSpy = jasmine.createSpy;

Expand All @@ -15,6 +16,7 @@ class MockLaunchDialogService implements Partial<LaunchDialogService> {
}
class MockCustomerTicketingFacade implements Partial<CustomerTicketingFacade> {
createTicketEvent = createSpy().and.returnValue(EMPTY);
uploadAttachment = createSpy().and.returnValue(EMPTY);
}

class MockRoutingService implements Partial<RoutingService> {
Expand Down Expand Up @@ -66,23 +68,53 @@ describe('CustomerTicketingReopenDialogComponent', () => {
expect(customerTicketingFacade.createTicketEvent).not.toHaveBeenCalled();
});

it('should call createTicketEvent if the form is valid', () => {
const mockEvent = {
message: 'mockMessage',
toStatus: {
id: STATUS.INPROCESS,
name: STATUS_NAME.INPROCESS,
},
};
const mustWaitForAttachment = false;
describe('when the form is valid', () => {
beforeEach(() => {
component.form.get('message')?.setValue('mockMessage');
});

component.form.get('message')?.setValue('mockMessage');
component.reopenRequest();
it('should call createTicketEvent if the form is valid', () => {
const mockEvent = {
message: 'mockMessage',
toStatus: {
id: STATUS.INPROCESS,
name: STATUS_NAME.INPROCESS,
},
};
const mustWaitForAttachment = false;

component.reopenRequest();

expect(customerTicketingFacade.createTicketEvent).toHaveBeenCalledWith(
mockEvent,
mustWaitForAttachment
);
});

it('should upload attachements after creating ticket', () => {
const mockFileList: File[] = [
new File(['foo'], 'foo.txt', {
type: 'text/plain',
}),
];
(mockFileList as any).item = (i: number) => mockFileList[i]; // mock FileList's accessor
component.form.get('file')?.setValue(mockFileList);
const mockTicketEvent: TicketEvent = {
code: 'code-000001',
createdAt: 'mock-create-date',
author: 'mock-author',
message: 'mock-message',
addedByAgent: true,
ticketEventAttachments: [{}],
};
(
customerTicketingFacade.createTicketEvent as jasmine.Spy
).and.returnValue(of(mockTicketEvent));

component.reopenRequest();

expect(customerTicketingFacade.createTicketEvent).toHaveBeenCalledWith(
mockEvent,
mustWaitForAttachment
);
expect(customerTicketingFacade.uploadAttachment).toHaveBeenCalled();
});
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ import { ComponentFixture, TestBed } from '@angular/core/testing';
import { I18nTestingModule, RoutingService } from '@spartacus/core';
import {
CustomerTicketingFacade,
STATUS_NAME,
TicketDetails,
TicketStarter,
} from '@spartacus/customer-ticketing/root';
import { LaunchDialogService } from '@spartacus/storefront';
import { EMPTY, of } from 'rxjs';
import { EMPTY, of, throwError } from 'rxjs';
import { CustomerTicketingCreateDialogComponent } from './customer-ticketing-create-dialog.component';
import createSpy = jasmine.createSpy;

Expand Down Expand Up @@ -52,6 +54,7 @@ class MockCustomerTicketingFacade implements Partial<CustomerTicketingFacade> {
getTicketAssociatedObjects = createSpy().and.returnValue(
of(mockTicketAssociatedObjects)
);
uploadAttachment = createSpy().and.returnValue(EMPTY);
}

describe('CustomerTicketingCreateDialogComponent', () => {
Expand Down Expand Up @@ -94,14 +97,64 @@ describe('CustomerTicketingCreateDialogComponent', () => {
});

describe('trigger create ticket request', () => {
it('should call createTicket if the form is valid', () => {
component.form.get('message')?.setValue(mockTicketStarter.message);
component.form.get('subject')?.setValue(mockTicketStarter.subject);
component.form.get('ticketCategory')?.setValue(mockCategories);
component.form.get('associatedTo')?.setValue(mockTicketAssociatedObjects);
component.createTicketRequest();
describe('when the form is valid', () => {
beforeEach(() => {
component.form.get('message')?.setValue(mockTicketStarter.message);
component.form.get('subject')?.setValue(mockTicketStarter.subject);
component.form.get('ticketCategory')?.setValue(mockCategories);
component.form
.get('associatedTo')
?.setValue(mockTicketAssociatedObjects);
});

it('should call createTicket if the form is valid', () => {
component.createTicketRequest();

expect(customerTicketingFacade.createTicket).toHaveBeenCalled();
});

it('should upload attachments after creating the ticket', () => {
const mockFileList: File[] = [
new File(['foo'], 'foo.txt', {
type: 'text/plain',
}),
];
component.form.get('file')?.setValue(mockFileList);
const mockTicketDetails: TicketDetails = {
id: '000001',

status: { id: 'mock-status-id', name: STATUS_NAME.OPEN },
ticketEvents: [
{
code: 'code-000001',
createdAt: 'mock-create-date',
author: 'mock-author',
message: 'mock-message',
addedByAgent: true,
ticketEventAttachments: [{}],
},
],
};

(customerTicketingFacade.createTicket as jasmine.Spy).and.returnValue(
of(mockTicketDetails)
);

component.createTicketRequest();

expect(customerTicketingFacade.uploadAttachment).toHaveBeenCalled();
});

it('should close if there is an error creating the ticket', () => {
spyOn(component, 'close').and.callThrough();
(customerTicketingFacade.createTicket as jasmine.Spy).and.returnValue(
throwError(() => 'error')
);

component.createTicketRequest();

expect(customerTicketingFacade.createTicket).toHaveBeenCalled();
expect(component.close).toHaveBeenCalledWith('Something went wrong');
});
});

it('should not call createTicket if the form is invalid', () => {
Expand Down
Loading