Skip to content
This repository was archived by the owner on Dec 18, 2024. It is now read-only.

feat: Automatic publication of admins #40

Conversation

redwan-faris
Copy link

@redwan-faris redwan-faris commented Jun 10, 2024

This is a:

  • New feature - new behaviour has been implemented
  • 🐛 Bug fix - existing behaviour has been made to behave
  • ♻️ Refactor - the behaviour has not changed, just the implementation
  • Test backfill - tests for existing behaviour were added but the behaviour itself hasn't changed
  • ⚙️ Chore - maintenance task, behaviour and implementation haven't changed

Description

  • Purpose - the admin can add the suggestion and its will be published automatically without going to draft
  • How to check -
    login as admin and then add the suggestion and check it in the publication directly

Links

Author checklist

  • I have written a title that reflects the relevant ticket
  • I have written a description that says what the PR does and how to validate it
  • I have linked to the project board ticket (and any related PRs/issues) in the Links section
  • I have added a link to this PR to the ticket
  • I have made the PR to main from a branch named <category>/<name>, e.g. feature/edit-spaceships or bugfix/restore-oxygen
  • I have manually tested that the app still works correctly
  • I have requested reviewers here and in my team chat channel
  • I have spoken with my PM or TL about any parts of this task that may have become out-of-scope, or any additional improvements that I now realise may benefit my project
  • I have added tests, or new tests were not required
  • I have updated any documentation (e.g. diagrams, schemas), or documentation updates were not required

@textbook
Copy link
Member

Please do review the PR template in the description and fill it out accordingly.

@redwan-faris
Copy link
Author

Please do review the PR template in the description and fill it out accordingly.
I did that
Thank you

@kfklein15 kfklein15 requested review from textbook and safeamiiir June 13, 2024 09:06
Copy link
Member

@textbook textbook left a comment

Choose a reason for hiding this comment

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

The basic functionality (when an admin posts a resource, publish it immediately) works OK. But looking at how that's done, it's clear the suggested flow (.github/CONTRIBUTING.md) wasn't followed. The checklist in the PR template is intended as a reminder to actually do those things - link the issue, write the tests, update the docs, ...

Functionality

✅ When I suggest a resource as a non-admin, it is created as a draft. When I do it as an admin, it's immediately published.

💡 UI is misleading when an admin is using the Suggest form - it still tells them their submission will be reviewed by an admin:

Screenshot 2024-06-13 at 10 47 25

Implementation

❓ Are we doing too much in the controller - maybe the service should be deciding whether to create a draft or published resource (i.e. receiving both information about the resource and the person creating it, something like service.create(resource, user)) as that's part of our business logic not specific to to the transport layer.

❌ No E2E test

❌ No API integration test

❓ Do the docs need updating to reflect the changed behaviour of the endpoint?

Key

  • ✅ Nothing to change, just commenting
  • 💡 Possible change, or suggestion to think about in the future
  • ❓ Discussion required before approval
  • ❌ Change required before approval

Comment on lines 50 to 54
let isDraft = true;

if (req.superuser || req.user?.is_admin) {
isDraft = false;
}
Copy link
Member

Choose a reason for hiding this comment

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

💡 Using the optional chaining here is unnecessary - if req.user was null or undefined, this would already have crashed on line 48 (you could also have accessed is_admin there, to keep all references to the req.user in one place).

💡 I'd always try to avoid using let for something like this, we can determine the value straight away and make it const:

Suggested change
let isDraft = true;
if (req.superuser || req.user?.is_admin) {
isDraft = false;
}
const isDraft = (req.superuser || req.user?.is_admin) ? false : true;

But then having a conditional expression whose values are true and false seems a bit weird, just use the value directly (ref: https://en.wikipedia.org/wiki/De_Morgan%27s_laws):

Suggested change
let isDraft = true;
if (req.superuser || req.user?.is_admin) {
isDraft = false;
}
const isDraft = !req.superuser && !req.user?.is_admin;

@redwan-faris
Copy link
Author

The basic functionality (when an admin posts a resource, publish it immediately) works OK. But looking at how that's done, it's clear the suggested flow (.github/CONTRIBUTING.md) wasn't followed. The checklist in the PR template is intended as a reminder to actually do those things - link the issue, write the tests, update the docs, ...

Functionality

✅ When I suggest a resource as a non-admin, it is created as a draft. When I do it as an admin, it's immediately published.

💡 UI is misleading when an admin is using the Suggest form - it still tells them their submission will be reviewed by an admin:

Screenshot 2024-06-13 at 10 47 25

Implementation

❓ Are we doing too much in the controller - maybe the service should be deciding whether to create a draft or published resource (i.e. receiving both information about the resource and the person creating it, something like service.create(resource, user)) as that's part of our business logic not specific to to the transport layer.

❌ No E2E test

❌ No API integration test

❓ Do the docs need updating to reflect the changed behaviour of the endpoint?

Key

  • ✅ Nothing to change, just commenting
  • 💡 Possible change, or suggestion to think about in the future
  • ❓ Discussion required before approval
  • ❌ Change required before approval

Thank you for your time and effort in reviewing my code. I have refactored the code in the API section to make it clearer, placing each piece of code in its appropriate file. Additionally, I have modified the responses that appear on the client side.

However, as a backend developer, I am facing problems with client-side testing.

Could you help me with changing the authentication for the user? The test is failing because it signs in using the admin account by default, but I want to control the sign-in process so I can create tests for both types of roles in the system.

Thanks.

@kfklein15 kfklein15 requested a review from textbook June 17, 2024 15:26
@textbook
Copy link
Member

Could you help me with changing the authentication for the user? The test is failing because it signs in using the admin account by default, but I want to control the sign-in process so I can create tests for both types of roles in the system.

What test is failing, and what exactly is it saying? You can push work in progress to the branch, then it'll run in the pipeline and we can all see it.

Across the various existing E2E cases there are examples of signing in using both admin and non-admin users, so testing both roles should be resonably straightforward.

@redwan-faris
Copy link
Author

Could you help me with changing the authentication for the user? The test is failing because it signs in using the admin account by default, but I want to control the sign-in process so I can create tests for both types of roles in the system.

What test is failing, and what exactly is it saying? You can push work in progress to the branch, then it'll run in the pipeline and we can all see it.

Across the various existing E2E cases there are examples of signing in using both admin and non-admin users, so testing both roles should be resonably straightforward.

I apologize for the delayed response. This week, I am celebrating Eid, an important holiday in Iraq ,
e2e is ok for me and the testing is working now
I am talking about the testing in the client side
how ever I will push the code as soon as possible
Thank you

@redwan-faris
Copy link
Author

Could you help me with changing the authentication for the user? The test is failing because it signs in using the admin account by default, but I want to control the sign-in process so I can create tests for both types of roles in the system.

What test is failing, and what exactly is it saying? You can push work in progress to the branch, then it'll run in the pipeline and we can all see it.
Across the various existing E2E cases there are examples of signing in using both admin and non-admin users, so testing both roles should be resonably straightforward.

I apologize for the delayed response. This week, I am celebrating Eid, an important holiday in Iraq , e2e is ok for me and the testing is working now I am talking about the testing in the client side how ever I will push the code as soon as possible Thank you

@textbook

@textbook
Copy link
Member

I have seen those messages. Do you have a specific question? You can see the tests failing in the pipeline, if that's what you're asking about - they give a lot of feedback, and I don't think "failing because it signs in using the admin account by default" is a correct interpretation of what's happening - the client-side tests don't sign in at all, the network layer is mocked with MSW.

@redwan-faris
Copy link
Author

redwan-faris commented Jun 21, 2024

I have seen those messages. Do you have a specific question? You can see the tests failing in the pipeline, if that's what you're asking about - they give a lot of feedback, and I don't think "failing because it signs in using the admin account by default" is a correct interpretation of what's happening - the client-side tests don't sign in at all, the network layer is mocked with MSW.

I think every thing related to tested is done now
Api testing
E2E testing
Client side testing

The swagger does not requeired to update I think because the only think that changes is the response of resource creation
when you are admin the draft will be false

Also is there any project linked with this repo to link the ticket?

Thank you for your time
@textbook

Copy link
Member

@textbook textbook left a comment

Choose a reason for hiding this comment

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

Thank you for the iteration, the test coverage is much improved. How did you find writing them? What about the refactoring from the controller to the service, what did you think of that?

is there any project linked with this repo to link the ticket?

You can just link the issue, #11

Comment on lines +29 to +37
if (requestBody.draft) {
await expect(
screen.findByText(/thank you for suggesting a resource/i)
).resolves.toHaveClass("message", "success");
} else {
await expect(
screen.findByText(/thank you for publishing a resource/i)
).resolves.toHaveClass("message", "success");
}
Copy link
Member

Choose a reason for hiding this comment

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

❌ You should pretty much never have conditional logic in tests. Only one of these cases is ever actually tested, there's no test where "suggesting" would be shown (which is what made them start failing in the first place), so including the other branch just confuses the issue and implies that's tested when it isn't.

❌ It's also incorrect - whether it shows "suggesting" or "publishing" isn't a matter of the request body (which never has a draft property - this should be clear from the assertions on it), it's a matter of the response body (which is an empty object in all of these tests).

Copy link
Author

Choose a reason for hiding this comment

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

ok I got that thanks

<p>
Please use the form below to submit a suggestion. Note that it will not
{isAdmin
? "Please use the form below to submit a resource. It's will appear immediately to the home page because you are administrator"
Copy link
Member

Choose a reason for hiding this comment

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

💡 Typos in UI text

Suggested change
? "Please use the form below to submit a resource. It's will appear immediately to the home page because you are administrator"
? "Please use the form below to submit a resource. It will appear immediately on the home page because you are administrator."

Comment on lines +134 to +138
cy.request({
headers: { Authorization: `Bearer ${Cypress.env("SUDO_TOKEN")}` },
method: "PATCH",
url: `/api/resources/${created.id}`,
});
Copy link
Member

Choose a reason for hiding this comment

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

❌ The PATCH request is to publish the resource, so that it shows up on the home page, which doesn't make sense in a test where: 1. the resource is already published (because the user is an admin); and 2. the home page isn't subsequently visited anyway.

Copy link
Author

Choose a reason for hiding this comment

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

ohhh that right :( mybe I forgot to delete it

@@ -385,4 +385,33 @@ describe("/api/resources", () => {
expect(published).toMatchObject({ publisher: admin.id, source: user.id });
});
});

describe("POST / - Auto publish for the admin resource", () => {
Copy link
Member

Choose a reason for hiding this comment

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

💡 This should really appear under the existing POST / group of tests; you can nest describe blocks where you really need separate contexts:

describe("/api/resources", () => {
  describe("POST /", () => {
    describe("as a user", () => {
      // ...
    });
  
    describe("as an admin", () => {
      // ...
    });
  });
});

Comment on lines +113 to +117
cy.visit("/");

cy.task("seed", { users: [admin] });
cy.logInAs("[email protected]");
cy.visit("/");
Copy link
Member

Choose a reason for hiding this comment

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

💡 It seems odd to visit the page, then update the DB, then login, then reload the home page (which you're on after logging in), maybe:

Suggested change
cy.visit("/");
cy.task("seed", { users: [admin] });
cy.logInAs("[email protected]");
cy.visit("/");
cy.task("seed", { users: [admin] });
cy.visit("/");
cy.logInAs("[email protected]");

@@ -12,7 +13,8 @@ export default function Suggest() {
const [topics, setTopics] = useState(undefined);
const resourceService = useService(ResourceService);
const topicService = useService(TopicService);

const user = usePrincipal();
const isAdmin = user && user.is_admin;
Copy link
Member

Choose a reason for hiding this comment

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

💡 or maybe

Suggested change
const isAdmin = user && user.is_admin;
const isAdmin = user?.is_admin;

Comment on lines +31 to +33
text: resource.draft
? "Thank you for suggesting a resource!"
: "Thank you for publishing a resource!",
Copy link
Member

Choose a reason for hiding this comment

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

✅ This is neat, basing it on the response means it continues to work even if the logic around roles changes later on.

@@ -41,11 +45,13 @@ export default function Suggest() {

return (
<>
<h2>Suggest a resource</h2>
<h2>{isAdmin ? "Publish a resource" : "Suggest a resource"}</h2>
Copy link
Member

Choose a reason for hiding this comment

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

💡 or

Suggested change
<h2>{isAdmin ? "Publish a resource" : "Suggest a resource"}</h2>
<h2>{isAdmin ? "Publish" : "Suggest"} a resource</h2>

Copy link
Member

Choose a reason for hiding this comment

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

💡 Continuing from the comment on the nav, this now has lots of separate checks of the same thing, which is a bit awkward. It'd be neater to have one higher-level e.g. isAdmin ? <Publish {...} /> : <Suggest {...} />.

Comment on lines +406 to +414
expect(body).toMatchObject({
title: resource.title,
url: resource.url,
draft: false,
id: expect.stringMatching(patterns.UUID),
source: id,
description: null,
accession: expect.stringMatching(patterns.DATETIME),
});
Copy link
Member

Choose a reason for hiding this comment

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

💡 Most of this is already asserted on in other tests, I wonder if the core logic being tested here would be clearer if the assertion was more focused:

Suggested change
expect(body).toMatchObject({
title: resource.title,
url: resource.url,
draft: false,
id: expect.stringMatching(patterns.UUID),
source: id,
description: null,
accession: expect.stringMatching(patterns.DATETIME),
});
expect(body).toHaveProperty("draft", false);

@textbook
Copy link
Member

This is now complete from the application perspective.

@textbook textbook closed this Jun 21, 2024
@redwan-faris
Copy link
Author

thank you for your effors and comments that I will sure work on them in the future

@redwan-faris
Copy link
Author

Thank you for the iteration, the test coverage is much improved. How did you find writing them? What about the refactoring from the controller to the service, what did you think of that?

is there any project linked with this repo to link the ticket?

You can just link the issue, #11

I have reviewed the client testing and end-to-end (e2e) testing, and I found them to be very useful for completing the task. Regarding the controller logic, I realized I had misunderstood the project's code structure. I initially thought all logic should be placed in the service layer, but I noticed some validation and checks being performed in the controller as well. However, I now understand that the correct approach is indeed to place most of the business logic in the service layer.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants