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

[GSoC2024] Cannot read properties of null (reading 'annotations') #7363 #7704

Closed

Conversation

MKBenjie
Copy link

@MKBenjie MKBenjie commented Mar 30, 2024

Motivation and context

How has this been tested?

Checklist

  • I submit my changes into the develop branch
  • I have created a changelog fragment
  • I have updated the documentation accordingly
  • I have added tests to cover my changes
  • I have linked related issues (see GitHub docs)
  • I have increased versions of npm packages if it is necessary
    (cvat-canvas,
    cvat-core,
    cvat-data and
    cvat-ui)

License

  • I submit my code changes under the same MIT License that covers the project.
    Feel free to contact the maintainers if that's a concern.

@MKBenjie MKBenjie requested a review from bsekachev as a code owner March 30, 2024 03:16
Comment on lines 92 to 105
test('handle page interrupt during annotation retrieval', async () => {
const job = (await cvat.jobs.get({ jobID: 101 }))[0];

// Mocking the behavior of job.annotations.get() to simulate a page interrupt
const mockAnnotationsGet = jest.spyOn(job.annotations, 'get');

// Reject the promise with an error to simulate a page interrupt
mockAnnotationsGet.mockRejectedValueOnce(new Error("Cannot read properties of null (reading 'annotations')"));

// Expectation: Retrieving annotations should throw an error
await expect(job.annotations.get(0)).rejects.toThrow("Cannot read properties of null (reading 'annotations')");

// Ensuring that job.annotations.get() was called with the correct arguments
expect(mockAnnotationsGet).toHaveBeenCalledWith(0);
Copy link
Member

Choose a reason for hiding this comment

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

  1. The code does not make sense, because the test tests itself
  2. Perhaps we need Cypress E2E tests to cover the bugfix, not jest. Because issue on cvat-ui level. On cvat-core level we can't even reproduce the problem.

Copy link
Author

Choose a reason for hiding this comment

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

The test was aiming to simulate a scenario where fetching annotations encounters an error. It was meant for verifying that the method correctly throws an error with the expected message when encountering a page interrupt.

If the issue is more related to UI behavior, then let me focus on E2E tests with Cypress.

let currentPath = window.location.pathname;

// Listen for popstate events (back/forward navigation)
window.addEventListener('popstate', () => {
Copy link
Member

Choose a reason for hiding this comment

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

popstate event listener is never removed. Memory leak, because fetchAnnotationsAsync may be called plenty of times.

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 should remove the event listener after it's triggered

window.addEventListener('popstate', () => {
const newPath = window.location.pathname;
if (newPath !== currentPath) {
console.log('Navigation interruption detected.');
Copy link
Member

Choose a reason for hiding this comment

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

we do not need logging in production code

Copy link
Author

Choose a reason for hiding this comment

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

Let me remove all

maxZ,
},
// Check if navigation interruption occurred
navigationInterruptionDetected((interrupted: boolean) => {
Copy link
Member

@bsekachev bsekachev Apr 1, 2024

Choose a reason for hiding this comment

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

From the code I see:

  1. We fetch annotations in line 318
  2. We call navigationInterruptionDetected with callback passed
    2.1. Callback with true argument will be called only if postate event was dispatched.
    2.2. Callback never called with false argument.

Condition in line 322 is always false, so, I am not sure how this code is supposed to work. Did you test it?

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 also see errors in my logic of handling this now. What do you think of handling this issue in such away.

  1. I separate the handling of navigation interruptions from the handling of fetching errors.
  2. I use a flag to track whether a navigation interruption occurred during the fetching process.
  3. Then check if navigation interruption occurred , dispatch success action if no interruption AND dispatch FETCH_ANNOTATIONS_FAILED only if not due to navigation interruption
  4. Then navigationInterruptionDetected function now returns a function that removes the event listener when it's no longer needed. So that that the event listener is cleaned up to prevent memory leaks.

@MKBenjie MKBenjie requested a review from bsekachev April 9, 2024 21:34
@bsekachev
Copy link
Member

Thank you for trying to contribute.
Unfortunately we are not ready to accept the patch as is, sorry.

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.

2 participants