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

✨ [Feature] :added new hooks useHash, useHashHistory, useClipboard and useOrigin #488

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

haseeb5555
Copy link

-key changes

four new hooks ✔️
docs ✔️
test cases✔️

Copy link

changeset-bot bot commented Feb 17, 2024

⚠️ No Changeset found

Latest commit: d228b54

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@juliencrn juliencrn added the feature request request a feature or hook to be added label Feb 20, 2024
Copy link
Contributor

@BlankParticle BlankParticle left a comment

Choose a reason for hiding this comment

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

Overall, 5 out of 7 test cases are failing. Every hook is written differently. Test cases and demos don't make sense for some hooks. Also there are 4 hooks in this 1 PR that shouldn't be the case.

Comment on lines +15 to +18

// Fast-forward time by 2000 milliseconds
await new Promise(resolve => setTimeout(resolve, 2000));

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think that works when you are fast forwarding time in tests, you should use vitest.useFakeTimers() at the start of test, then vitest.advanceTimersByTime(delay) where you want to forward the time

});

// The isCopied state should be true immediately after copying
expect(result.current.isCopied).toBe(true);
Copy link
Contributor

Choose a reason for hiding this comment

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

This wouldn't work as clipboard.writeText is an async function and you are setting the value of isCopied in the then callback. So the value doesn't update immediately

Comment on lines +3 to +20
export function useClipboard({ timeout = 2000 }: { timeout?: number }) {
const [isCopied, setIsCopied] = useState<Boolean>(false)

const copyToClipboard = (value: string) => {
if (!value) return
if (typeof window === 'undefined' || !navigator.clipboard?.writeText) return

navigator.clipboard.writeText(value).then(() => {
setIsCopied(true)

setTimeout(() => {
setIsCopied(false)
}, timeout)
})
}

return { isCopied, copyToClipboard }
}
Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think we need another useClipboard while useCopyToClipboard exists, If you want the functionallity of setting isCopied and restting it after timeout you can do that by yourself outside of the hook. Or add that feature to the existing hook.
Don't create duplicate hooks as they tend to be confusing.

Comment on lines +9 to +11
originalHash = window.location.hash;
originalRemoveEventListener = window.removeEventListener;

Copy link
Contributor

Choose a reason for hiding this comment

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

I think you wanted to assign vi.fn() to window.removeEventListener, as you are testing later if removeEventListener was called or not. But it would fail as removeEventListner is not a spy.

Comment on lines +28 to +32
// Simulate a hashchange event with a new hash value
const newHash = "#newHash";
window.location.hash = newHash;
const event = new Event('hashchange');
window.dispatchEvent(event);
Copy link
Contributor

Choose a reason for hiding this comment

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

You might want to call it inside act(()=>{/* */})

Comment on lines +17 to +21
it('should return empty string before component has mounted', () => {
const { result } = renderHook(() => useOrigin());

expect(result.current).toBe('');
});
Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I know, renderHook mounts the component. so the test doesn't make sense. Also Origin is never "", for the sake of test the origin is supposed to be http://localhost:3000

Comment on lines +17 to +21
it('should return empty string before component has mounted', () => {
const { result } = renderHook(() => useOrigin());

expect(result.current).toBe('');
});
Copy link
Contributor

Choose a reason for hiding this comment

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

As far as I know, renderHook mounts the component. so the test doesn't make sense. Also Origin is never "", for the sake of test the origin is supposed to be http://localhost:3000

Comment on lines +5 to +12
it('should return empty string if window.location.origin is not available', () => {
const originalLocation = window.location;
delete (window as any).location;
window.location = { origin: '' }as unknown as Location;

const { result } = renderHook(() => useOrigin());

expect(result.current).toBe('');
Copy link
Contributor

Choose a reason for hiding this comment

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

You want to test if window.location.origin is not available, you delete window.location but then you are setting origin to "" yourself. Then what is the point of doing the test?

Comment on lines +23 to +42
it('should return window.location.origin after component has mounted', async () => {
const originalLocation = window.location;
delete (window as any).location;
window.location = { origin: 'https://usehooks-ts.com' } as unknown as Location;

let result: any;
await act(async () => {
result = renderHook(() => useOrigin()).result;
});

expect(result.current).toBe('');

await act(async () => {
await new Promise(resolve => setTimeout(resolve, 0)); // Waiting for the next microtask
});

expect(result.current).toBe('https://usehooks-ts.com');

window.location = originalLocation;
});
Copy link
Contributor

Choose a reason for hiding this comment

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

This whole test doesn't make any sense. Also I don't want to point out same things about fakeTimers as I have mentioned them previously.

Comment on lines +4 to +17
export const useOrigin = () => {
const [mounted, setMounted] = useState(false);

useEffect(() => {
setMounted(true);
}, []);

const origin = typeof window !== "undefined" && window.location.origin ? window.location.origin : "";

if (!mounted) {
return "";
}

return origin;
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you need a mounted when you are setting origin to "" based on typeof window !== "undefined"

Copy link
Author

Choose a reason for hiding this comment

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

Got it thanks for feedback. Will fix it soon

@haseeb5555 haseeb5555 closed this Feb 20, 2024
@haseeb5555 haseeb5555 reopened this Feb 20, 2024
Copy link

@jiji-hoon96 jiji-hoon96 left a comment

Choose a reason for hiding this comment

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

useOrigin and useHashHistory are so interesting.

return () => {
window.removeEventListener("hashchange", handleHashChange);
};
}, []);

Choose a reason for hiding this comment

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

If I modify the code so that it renders anew every time the value of the hash changes, will this cause problems?

Copy link
Author

Choose a reason for hiding this comment

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

Modifying the code to re-render on hash changes shouldn't inherently cause problems. It's done to ensure the component reacts to hash value changes accurately.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature request request a feature or hook to be added
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants