Skip to content

API: Fix tags update on updating a note #2649

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

Merged
merged 8 commits into from
Mar 13, 2020
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 47 additions & 0 deletions CliClient/tests/services_rest_Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ const Folder = require('lib/models/Folder');
const Resource = require('lib/models/Resource');
const Note = require('lib/models/Note');
const Tag = require('lib/models/Tag');
const NoteTag = require('lib/models/NoteTag');
const { shim } = require('lib/shim');

jasmine.DEFAULT_TIMEOUT_INTERVAL = 10000;
Expand Down Expand Up @@ -326,4 +327,50 @@ describe('services_rest_Api', function() {
expect(response3.length).toBe(2);
}));

it('should update tags when updating notes', asyncTest(async () => {
const tag1 = await Tag.save({ title: 'mon étiquette 1' });
const tag2 = await Tag.save({ title: 'mon étiquette 2' });
const tag3 = await Tag.save({ title: 'mon étiquette 3' });
const newTagTitle = 'mon étiquette 4';

const note = await Note.save({
title: 'ma note un',
});
Tag.addNote(tag1.id, note.id);
Tag.addNote(tag2.id, note.id);

const response1 = await api.route('PUT', `notes/${note.id}`, null, JSON.stringify({
tags: `${tag1.title},${tag3.title}`,
}));
const tagIds1 = await NoteTag.tagIdsByNoteId(note.id);
expect(response1.tags === `${tag1.title},${tag3.title}`).toBe(true);
expect(tagIds1.length === 2).toBe(true);
expect(tagIds1.includes(tag1.id)).toBe(true);
expect(tagIds1.includes(tag3.id)).toBe(true);

const response2 = await api.route('PUT', `notes/${note.id}`, null, JSON.stringify({
tags: `${tag2.title},${newTagTitle}`,
}));
const newTag = await Tag.loadByTitle(newTagTitle);
const tagIds2 = await NoteTag.tagIdsByNoteId(note.id);
expect(response2.tags === `${tag2.title},${newTag.title}`).toBe(true);
expect(tagIds2.length === 2).toBe(true);
expect(tagIds2.includes(tag2.id)).toBe(true);
expect(tagIds2.includes(newTag.id)).toBe(true);

const response3 = await api.route('PUT', `notes/${note.id}`, null, JSON.stringify({
title: 'Some other title',
}));
const tagIds3 = await NoteTag.tagIdsByNoteId(note.id);
expect(tagIds3.length === 2).toBe(true);
expect(tagIds3.includes(tag2.id)).toBe(true);
expect(tagIds3.includes(newTag.id)).toBe(true);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This test case checks the case when the tags property is not mentioned during the request. So, the tags associated with the note does not differ from the previous test case.

Also, I haven't checked response3.tags because it is undefined when tags property isn't mentioned during the API request. So, I skipped that check.

Copy link
Contributor

Choose a reason for hiding this comment

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

because it is undefined when tags property isn't mentioned

That can be tested too! If it wasn't returned as undefined, then it would be a problem.


const response4 = await api.route('PUT', `notes/${note.id}`, null, JSON.stringify({
tags: '',
}));
const tagIds4 = await NoteTag.tagIdsByNoteId(note.id);
expect(response4.tags === '').toBe(true);
expect(tagIds4.length === 0).toBe(true);
}));
Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this test case, the tags property is mentioned explicitly with a ''. So, all the tags associated with the note are removed from the note.

Copy link
Contributor

Choose a reason for hiding this comment

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

Generally, for future maintenance, it would be better to separate the test cases into 3 or 4 smaller test cases rather than one big one. This also helps avoid using the 1,2,3,4 variable names too. Sometimes it is too inefficient, but by default it is preferred.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I restructured all the test cases into separate ones. But, I'm not sure if I did it right. I have used lengthy test case descriptions for some test cases. Please review and let me know if I'm doing it right.

Copy link
Contributor

Choose a reason for hiding this comment

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

Looks good!

});
Copy link
Contributor

@miciasto miciasto Mar 3, 2020

Choose a reason for hiding this comment

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

What happens if the user accidently sets a tag name that doesn't exist? Is it possible to do via this interface? If it is, then we should add a test for 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.

If the user sets a tag name that doesn't exist via this interface, it creates the tags and then adds it to the note. I forgot to write a test case for that. I will fix the unit test.

18 changes: 18 additions & 0 deletions ReactNativeClient/lib/services/rest/Api.js
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,24 @@ class Api {
return note;
}

if (request.method === 'PUT') {
const note = await Note.load(id);

if (!note) throw new ErrorNotFound();

let updatedNote = await this.defaultAction_(BaseModel.TYPE_NOTE, request, id, link);

const requestNote = JSON.parse(request.body);
if (requestNote.tags === '') {
await Tag.setNoteTagsByTitles(id, '');
} else if (requestNote.tags) {
const tagTitles = requestNote.tags.split(',');
await Tag.setNoteTagsByTitles(id, tagTitles);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Can this be reduced to a single if statement? I don't think you need two branches.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, I just realized two branches weren't necessary. I changed the code to use just a single if.


return updatedNote;
}

return this.defaultAction_(BaseModel.TYPE_NOTE, request, id, link);
}

Expand Down