How to "Actually" Test an Angular 2 Service - api

I am new to testing calls to an API. I have this unit test code in Angular 2:
beforeEach(inject([JobListService, MockBackend],
(testedService: JobListService, mockBackend: MockBackend) => {
service = testedService;
backend = mockBackend;
backend.connections.subscribe((c) => {
c.mockRespond(new Response(
new ResponseOptions({body: JSON.stringify(JOBLISTMOCK)})
));
});
}));
describe('getAll', () => {
it('should return jobs', () => {
service.getAll(1, 10, '0').subscribe(response => {
console.log(response.data.length);
expect(response.data.data.length).toBeGreaterThan(0);
});
});
it('should return jobs based on company ID', () => {
service.getAll(1, 10, '26').subscribe(response => {
console.log(response.data.data.length);
expect(response.data.data.length).toEqual(1);
});
});
});
it has the url structure:
http://example.com/api/jobs/1/10/26
where first and second segment is pagination and the 3rd segment is a company ID.
I am testing this service function:
getAll(page: number, pageSize: number, company: string): Observable<any> {
if (company !== 'null') {
return this.http.get(`${this.conf.apiUrl}/jobs/companies/get/${page}/${pageSize}/${company}`)
.map((response: Response) => response.json());
} else {
return this.http.get(`${this.conf.apiUrl}/jobs/companies/get/${page}/${pageSize}/0`)
.map((response: Response) => response.json());
}
}
I have this mock response:
{
'id': 13,
'title': 'Sample Title',
'valid_from': '2016-01-01',
'valid_to': '2016-02-01',
'field_id': '1',
'image': '',
'description': null,
'user_id': 0,
'company_id': 26,
'created_at': '2017-01-23 14:37:01',
'updated_at': '2017-01-23 14:37:01',
'fields': {
'field_id': 1,
'name': 'Respiratory Therapy Technician'
}
},
{
'id': 15,
'title': 'Sample Title',
'valid_from': '2016-01-01',
'valid_to': '2016-02-01',
'field_id': '1',
'image': 'asd',
'description': 'This is my sample des',
'user_id': 0,
'company_id': 0,
'created_at': '2017-01-23 14:37:27',
'updated_at': '2017-01-23 14:37:27',
'fields': {
'field_id': 1,
'name': 'Respiratory Therapy Technician'
}
}
}
the 2nd one fails, obviously, because my mock response is set to companies that have 0 and 26 as IDs.
I get that I am mocking a response via a mockbackend but what I want is to test the function such that getAll() returns only the jobs with company_id 26. But my mock response is static. Is there anyway that I can make a "dynamic mock backend" that will work with what I want to test?

Related

Make JavaScript variable external data?

In a script tag in my HTML file I have a JavaScript function as such. Notice the part where it I create the variable const event = { . My question how in the same folder as the HTML file could I create a file that is only the event variable and refer to in in the code. Could this externally referenced data be a JSON file? Thanks
async function insertEvents() {
let response;
try {
const event = {
'summary': 'Martha Dentist',
'location': '800 Howard St., San Francisco, CA 94103',
'description': 'Take Martha to dentist.',
'start': {
'dateTime': '2023-02-28T07:00:00-07:00',
'timeZone': 'America/Los_Angeles'
},
'end': {
'dateTime': '2023-02-28T08:00:00-07:00',
'timeZone': 'America/Los_Angeles'
},
'recurrence': [
'RRULE:FREQ=DAILY;COUNT=8'
],
'attendees': [
{'email': 'charles#datatech.com'},
{'email': 'datatech#gmail.com'}
],
'reminders': {
'useDefault': false,
'overrides': [
{'method': 'email', 'minutes': 24 * 60},
{'method': 'popup', 'minutes': 10}
]
}
};
const request = {
'calendarId': 'primary',
'resource': event
};
response = await gapi.client.calendar.events.insert(request);
} catch (err) {
document.getElementById('content').innerText = err.message;
return;
}
const events = response.result.items;
if (!events || events.length == 0) {
document.getElementById('content').innerText = 'No events found.';
return;
}
}
I did not know if you can refer to another JavaScript or JSON file in a function.

Freeze redirect in cypress

I would like to test a GA4 product click event. For this I write the required data in the data layer and I want to see if the correct data is in the data layer. However, when I click on the product in Cypress, the redirect is faster than the test can read the data layer. Is there any way I can pause or freeze the redirect?
Here the expectet data in the Datalayer:
select_item: {
event: 'select_item',
ecommerce: {
item_name: 'Artiklename',
item_id: '000000',
price: 1.19,
currency: 'EUR',
item_brand: 'Brand',
item_category: 'category',
item_category2: 'category2',
item_category3: 'category3',
item_category4: 'category4',
index: 1,
quantity: 1,
item_list_name: "List Name"
},
},
Here the actual Test:
context('Google Analytics 4: should track select_item event', function () {
it('should track select item on search page', function () {
cy.getTrackingData('expressShippingArticle', 'select_item').then(
(expectedSelectItemEvent) => {
// act
cy.visitWithBasicAuth(
routes.category.resultList(
'000/SomeArticle'
)
)
//assert
cy.getSpecificEventFromDataLayer('select_item').then(
(event) => {
cy.wrap(event).should('not.exist')
}
)
// act
cy.get(selectors.resultList.productInResultList)
.first()
.click()
cy.getSpecificEventFromDataLayer('select_item').then(
(actualSelectItemEvent) => {
cy.wrap(actualSelectItemEvent, { timeout: 0 }).should(
spok(expectedSelectItemEvent)
)
}
)
}
)
})
})
Not sure if this works with GA4, but if you want to delay a network request/response add an intercept with delay option
cy.intercept(redirect-url, (req) => {
req.reply(res => {
res.setDelay(2000)
})
})
// act
cy.get(selectors.resultList.productInResultList).first().click()
...

Add object to array in nested json object - Redux

I'm getting a hard time adding an object to an array inside a JSON object.
This is my state:
const DATA =
{
data: [
{
id: 1,
routeName: 'my 2 route',
origin: 'Tel Aviv',
destination: 'Netanya',
date: '25-01-2021',
km: '60',
stops: [
{
id: 0,
address: 'test',
lat: '32.0853',
lon: '34.7818',
customerName: 'test',
tel: '00000',
},
{
id: 1,
address: 'adddress',
lat: '32.0853',
lon: '34.7818',
customerName: 'test',
tel: '00000',
}
],
},
{
id: 2,
routeName: 'my second route',
origin: 'Holon',
destination: 'Hadera',
date: '12-02-2021',
km: '70',
stops: [
{
id: 0,
address: 'address0',
lat: '32.0853',
lon: '34.7818',
customerName: 'customer0',
tel: '00000000',
},
{
id: 1,
address: 'address1',
lat: '32.0853',
lon: '34.7818',
customerName: 'customer1',
tel: '00000000',
},
],
},
],
}
I don't know how to write the reducer, tried few ways but the state doesn't change.
My reducer gets the route id + stop to add this route.
I will be happy for some help here :)
You'll need to find the parent route using the route's id, and then you'll need to create a new stops array by spreading, and adding the new stop.
You can use Array.findIndex() to find the actual route, and the slice the array, and update the route. However, another simple option is to map the data's routes, and update the route with the matching id.
const routeReducer = (state, { type, payload: { routeId, stop } }) => {
switch (type) {
case 'ADD_STOP':
return {
...state,
data: state.data.map(route => route.id === routeId ? {
...route,
stops: [...route.stops, stop]
} : route)
}
}
}
Usually in redux it's better to normalize the state, which makes it easier to update single items.
You could have a reducer that did something like this:
const updateItemInArray = (array, itemId, updateItemCallback) => {
return array.map(item => {
if (item.id !== itemId) return item;
// Use the provided callback to create an updated item
return updateItemCallback(item);
});
};
const data = (state = [], action) => {
switch (action.type) {
case 'ADD_STOP_SUCCESS':
return updateItemInArray(state, action.payload.routeId, (item) => ({...item, stops: [...item.stops, action.payload.stop]}))
default: return state;
}
}
When the action.type 'ADD_STOP_SUCCESS' is called the payload of the action would contain the new stop object you are wanting to add to the state.

How to override the response in Jasmine Spyon

I have an mockservice and i need to override the mock service response in particular test cases, but it is taking an value from the mock service instead of new response in spyon.
here i have a mock service and return some value.
export class MockService {
getProducts() {
const data = [{ 'productI': 1, 'productName': 'Phone', 'price': 19.96 },
{ 'productID': 3, 'productName': 'Phones', 'price': 19.96 },
{
'productID': 2, 'productName': 'Laptop', 'price': 2000.96
}];
return Observable.of(data);
}
}
In spec one of the test case i have getting the above response and test case success.
it('call subscribe get Products and get into success', () => {
spyOn(mockService, 'getProduct').and.returnValue(
observable.of();
)
});
component.ngOnInit();
In another test cases i need to test fail scenario.
it("Test 409 failure in service call',()=>{
spyOn(mockService, 'getProduct').and.returnValue(
throwError({status:409})
});
component.ngOnInit();
});
In this case , getting a value from predefined mock respone.Why it is not get into error after provide throwError in spyOn

Updating an array of Data in Vue JS

i'm trying to make a little DataTable in VueJS 2.0, and i've hit a bit of a roadblock, i'm making a call to a backend route to get some JSON from records in the Database, so far so good.
I want those records to populate an Array of GridData that i will later iterate through and display on my table.
The problem here is that it's not working...
Vue.http.post('/getData', data).then((response) => {
this.gridData = response.body;
});
I have my data setup as follows
data: () => {
return {
searchQuery: "",
columns: ['ID', 'Name', 'Campaign', 'Method', 'Limit Per Connection', 'Limit Per Day', 'Active', 'Successes', 'Failures', 'Last Ran'],
lastId: 0,
rowsPerPage: 10,
gridData: []
}
}
And my function that gets the data is called on the mounted hook
mounted() {
this.fetchData(this.lastId, this.rowsPerPage);
},
Am i doing anything wrong here?
You are using POST HTTP Request, instead of GET.POST is for creating new records in API/DB.
I think this should work for you
data() {
return {
searchQuery: "",
columns: ['ID', 'Name', 'Campaign', 'Method', 'Limit Per Connection', 'Limit Per Day', 'Active', 'Successes', 'Failures', 'Last Ran'],
lastId: 0,
rowsPerPage: 10,
gridData: []
}
},
created() {
this.fetchData()
},
methods: {
fetchData() {
this.$http.get('/getData')
.then(result => {
this.gridData = result.data
// or this.gridData = result.json()
})
}
}