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

Fixes #3615: Add author, title, publishDate fields to '/' route #3764

Closed
wants to merge 26 commits into from

Conversation

liutng
Copy link
Contributor

@liutng liutng commented Nov 17, 2022

Issue This PR Addresses

Closes #3615

Type of Change

  • Bugfix: Change which fixes an issue
  • New Feature: Change which adds functionality
  • Documentation Update: Change which improves documentation
  • UI: Change which improves UI

Description

In this PR, an extra query param expand is added to the URL /posts in posts services.
When expand=1, there will be extra data of author, title, and publishDate returned.
When expand does not equal 1, or expand does not present in the request, the request will return the data like before.

Steps to test the PR

Load the posts page in the react-native app, and observe if the extra fields of data are returned by /posts. This requires the react-native app to add "expand=1" to its request query params of /posts as well.

Here's what does the request and data look like.
image

Checklist

  • Quality: This PR builds and passes our npm test and works locally
  • Tests: This PR includes thorough tests or an explanation of why it does not
  • Screenshots: This PR includes screenshots or GIFs of the changes made or an explanation of why it does not (if applicable)
  • Documentation: This PR includes updated/added documentation to user exposed functionality or configuration variables are added/changed or an explanation of why it does not(if applicable)

@gitpod-io
Copy link

gitpod-io bot commented Nov 17, 2022

P-DR0ZD
P-DR0ZD previously approved these changes Nov 17, 2022
Copy link
Contributor

@P-DR0ZD P-DR0ZD left a comment

Choose a reason for hiding this comment

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

Looks Good

@liutng
Copy link
Contributor Author

liutng commented Nov 17, 2022

Looks Good

Thanks.

@manekenpix manekenpix changed the title Fix: Issue #3615 Fixes #3615: Add author, title, publishDate fields to '/' route Nov 17, 2022
@@ -69,6 +69,19 @@ describe('/posts', () => {
expect(res.body.length).toBeGreaterThan(0);
});

test('request posts with a valid expand query param', async () => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Please add a test for expand=1 as well.

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 tried to cover this scenario in my test but it either returns empty data or timeout, although the API works fine if I were requesting with my browser or Postman. Got any clue what might cause this problem?

Copy link
Contributor

Choose a reason for hiding this comment

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

Debug it, add logging, etc. You should have 150 posts created before this test runs. We can't land this change without a test that proves it works.

ids
let data;
if (expand === 1) {
data = await Promise.all(
Copy link
Contributor

Choose a reason for hiding this comment

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

This can fail, needs try/catch

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thank for the suggestion, a try/catch block is now added to wrap Promise.all().

Copy link
Contributor

Choose a reason for hiding this comment

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

When you say "is now added," there is nothing here. Please push your changes.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, I forgot to push my code, it's now pushed.

Copy link
Contributor

@humphd humphd left a comment

Choose a reason for hiding this comment

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

Looks like the test changes are still pending? What's happening with those?

@liutng
Copy link
Contributor Author

liutng commented Nov 17, 2022

Looks like the test changes are still pending? What's happening with those?

I'm still working on the test where expand=1.

@liutng
Copy link
Contributor Author

liutng commented Nov 18, 2022

Sorry for the delay. Finally, the test is working. I added extra feed data to posts.test.js to make it work. The code has been pushed now.

const res = await request(app).get('/?page=1&expand=1');
expect(res.status).toEqual(200);
// This will depend on the env value, so as long as we get back something.
expect(res.body.length).toBeGreaterThan(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

This isn't enough. In the case that you include expand=1, we'll expect the shape of the objects returned in the array to be different. Please add some logic to the tests to deal with the case of expand=1 and without, looking at the properties in the objects.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, I've pushed a revised test that now checks the extra properties in the return data when expand=1.

Copy link
Contributor

Choose a reason for hiding this comment

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

This is getting better, but still doesn't test what we need.

Use Jest's arrayContaining and objectContaining to look for one item that has the shape/values you expect in the results returned.

@@ -60,14 +60,31 @@ posts.get('/', validatePostsQuery(), async (req, res, next) => {
first: `/posts?per_page=${perPage}&page=${1}`,
last: `/posts?per_page=${perPage}&page=${Math.floor(postsCount / perPage)}`,
});
res.json(
ids
let data = {};
Copy link
Contributor

Choose a reason for hiding this comment

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

nit: don't bother assigning a value here, since you'll throw it away in the if/else that follows. Another pattern you could use is to move the if/else to a function:

try {
  const data = await prepareData(ids, expand === 1);
  res.json(data);
} ... 

And your function could look like this (untested):

const prepareData = async (ids, shouldExpand) {
  if (shouldExpand) {
      return Promise.all(
        ids.map(async (id) => {
          // obtain the corresponding feed to populate the author's name to the return data.
          const post = await Post.byId(id);
          return {
            id,
            url: `${postsUrl}/${id}`,
            author: post.feed.author,
            title: post.title,
            publishDate: post.published,
          };
        })
      );
  } else
    return ids
      .map((id) => ({
        id,
        url: `${postsUrl}/${id}`,
      }))
  );
};

link: 'http://foo.link',
etag: 'etag',
lastModified: new Date('2009-09-07T22:23:00.544Z'),
githubUsername: 'githubusr',
Copy link
Contributor

Choose a reason for hiding this comment

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

s/githubusr/githubUsername/ to make it even more clear.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, what does this mean? Should I change the field name of githubUsername to something else? Or the value githubusr?

Copy link
Contributor

Choose a reason for hiding this comment

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

The value. It's easiest if the property name and value match (e.g., like etag above).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it, thank you for the suggestion, it's already fixed now and pushed.

const res = await request(app).get('/?page=1&expand=1');
expect(res.status).toEqual(200);
// This will depend on the env value, so as long as we get back something.
expect(res.body.length).toBeGreaterThan(0);
Copy link
Contributor

Choose a reason for hiding this comment

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

This is getting better, but still doesn't test what we need.

Use Jest's arrayContaining and objectContaining to look for one item that has the shape/values you expect in the results returned.

Copy link
Contributor

@humphd humphd left a comment

Choose a reason for hiding this comment

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

Nice, almost there.

@@ -7,11 +7,35 @@ const postsUrl = process.env.POSTS_URL || '/';

const posts = Router();

const prepareData = async (ids, shouldExpand = false) => {
if (shouldExpand) {
const data = await Promise.all(
Copy link
Contributor

Choose a reason for hiding this comment

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

No need for data or await here, just return the Promise directly:

return Promise.all(

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 tried directly to return Promise.all() without prefixing await. It will cause lint to complain. Here is what the complain looks like
image

Copy link
Contributor

Choose a reason for hiding this comment

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

OK, eslint is wrong here, but that's OK. Change to this:

const prepareData = (ids, shouldExpand = false) => {
  if(shouldExpand) {
    return Promise.all(...)
  }
  return Promise.resolve(...)
}

Copy link
Contributor Author

@liutng liutng Nov 21, 2022

Choose a reason for hiding this comment

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

Hi, I pushed a new commit but eslint still complains.

@@ -9,7 +9,7 @@ const posts = Router();

const prepareData = async (ids, shouldExpand = false) => {
Copy link
Contributor

Choose a reason for hiding this comment

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

Get rid of async here, we aren't going to await anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Got it. A new commit is pushed.

humphd
humphd previously approved these changes Nov 21, 2022
Copy link
Contributor

@humphd humphd left a comment

Choose a reason for hiding this comment

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

This looks good to me, nice work. Once this goes green on CI, please squash all 12 commits into 1, and rebase on latest master.

@liutng
Copy link
Contributor Author

liutng commented Nov 21, 2022

Ok, I will do it now. Thank you for reviewing my code.

cindyorangis and others added 22 commits November 21, 2022 11:31
* Delete text "snippet"
* Change solution approach to add eclipses
* Fix Twitch typo
* Fix class names
Update dependency row bottom border color to be lighter in dark mode

Make border style consistent across all rows

Make border style important

Co-authored-by: Kevan Yang <[email protected]>

Remove extra whitespace

Make dependency info cell border style important
* Fixed lint errors
* Wrapped Promise.all() with try/catch block because it might fail.
* Added test for `/post/` when expand=1
* Increased test granularity on the test
* Increased the test strength of expand=1
* Reduced code redundancy in posts.js
* Changed the pseudo-data in `posts.test.js` to make it more rational.
* Removed redundant variable assignment.
* Removed async in parepareData()
@liutng
Copy link
Contributor Author

liutng commented Nov 21, 2022

I tried everything I could to fix this PR. Maybe this Pull Request is beyond repairable.. Should I close this one and open a new one?

@humphd
Copy link
Contributor

humphd commented Nov 21, 2022

Sure, that's a good idea. It would be useful to figure out what you did wrong, so you can fix in the future. This workflow is something you need to master. Let me know if you need help.

@liutng
Copy link
Contributor Author

liutng commented Nov 21, 2022

Thank you, I will not hesitate to contact you when I need help and also the lesson I've learned from this time is never use any git command if I'm not aware of what this command does.

@liutng liutng closed this Nov 21, 2022
@liutng liutng deleted the issue-3165-fix branch November 21, 2022 17:43
@liutng liutng mentioned this pull request Nov 21, 2022
8 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[Post-services] Add author, title, publishDate fields to '/' route