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

feat(game-lobby): generation on server at demand #971

Merged
merged 4 commits into from
Oct 13, 2024

Conversation

antoinezanardi
Copy link
Owner

@antoinezanardi antoinezanardi commented Oct 13, 2024

Summary by CodeRabbit

  • New Features

    • Introduced a ClientOnly wrapper for several components in the Game Lobby, ensuring they are rendered only on the client side.
    • Added a new local storage management system for game options and audio settings.
  • Bug Fixes

    • Enhanced logic in the useDevice function to prevent errors in environments without a window object.
  • Tests

    • Updated test suite for the Game Lobby page to include the ClientOnly component, improving test coverage and validation of page behavior.
    • Revised tests for audio and game creation stores to reflect changes in local storage handling.

@antoinezanardi antoinezanardi added the 🚀 feature New feature or request label Oct 13, 2024
@antoinezanardi antoinezanardi self-assigned this Oct 13, 2024
Copy link

coderabbitai bot commented Oct 13, 2024

Caution

Review failed

The head commit changed during the review from a5727a2 to dc8cbe4.

Walkthrough

The changes in this pull request include modifications to the useDevice composable for improved touch device detection, the implementation of a ClientOnly wrapper in the game-lobby.vue file to ensure client-side rendering of specific components, and updates to local storage handling in various stores. Additionally, test suites for the useDevice composable, the Game Lobby page, and local storage functionalities have been updated to reflect these changes, ensuring proper functionality and coverage.

Changes

File Path Change Summary
app/composables/misc/useDevice.ts Enhanced logic for touch device detection; added check for window object existence.
app/pages/game-lobby.vue Introduced ClientOnly wrapper around multiple components to ensure client-side rendering.
app/components/pages/game-lobby/GameLobbyHeader/GameLobbyHeaderOptionsButton.vue Wrapped PrimeVueBadge in ClientOnly for client-side rendering.
app/stores/audio/useAudioStore.ts Replaced local storage handling with useLocalStorageStore; updated related test suite.
app/stores/enums/store.enum.ts Added LOCAL_STORAGE entry to StoreIds enum.
app/stores/game/create-game-dto/useCreateGameDtoStore.ts Updated local storage handling; added storeToRefs import; modified test suite.
app/stores/local-storage/useLocalStorageStore.ts Introduced new store for managing local storage for game options and audio settings.
tests/unit/specs/components/pages/game-lobby/GameLobbyHeader/GameLobbyHeaderOptionsButton.nuxt.spec.ts Updated tests to include ClientOnly stub and tooltip binding.
tests/unit/specs/stores/audio/useAudioStore.spec.ts Updated mocks for local storage handling.
tests/unit/specs/stores/game/create-game-dto/useCreateGameDtoStore.spec.ts Updated local storage mock to reflect new structure.
tests/unit/specs/stores/local-storage/useLocalStorageStore.nuxt.spec.ts Introduced new test file for useLocalStorageStore.

Possibly related PRs

Suggested labels

🔩 refactor

🐰 In a world of screens and touch,
Our little code hops, oh so much!
With ClientOnly snug and tight,
The game lobby shines, a pure delight!
A touch device check, clear as day,
Ensures our fun is here to stay! 🌟


Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

❤️ Share
🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Outside diff range and nitpick comments (5)
app/composables/misc/useDevice.ts (1)

8-13: Approve changes with suggestions for improvement

The addition of the window existence check is a good improvement to prevent errors during server-side rendering. However, consider the following suggestions:

  1. For Nuxt 3 applications, you might want to use useNuxtApp().$device for more accurate device detection. This would provide consistent results across server-side and client-side rendering.

  2. Add a comment explaining the purpose of the window check for better code maintainability.

Here's a potential refactor using useNuxtApp().$device:

import { useNuxtApp } from '#app'

function useDevice(): UseDevice {
  const nuxtApp = useNuxtApp()
  
  const isOnTouchDevice = computed<boolean>(() => {
    // Use Nuxt's built-in device detection
    return nuxtApp.$device.isMobile || nuxtApp.$device.isTablet
  });

  return {
    isOnTouchDevice,
  };
}

If you decide to keep the current implementation, consider adding a comment:

const isOnTouchDevice = computed<boolean>(() => {
  // Check if window is defined to avoid errors during server-side rendering
  if (typeof window === "undefined") {
    return false;
  }
  return "ontouchstart" in window || navigator.maxTouchPoints > 0;
});
nuxt.config.ts (1)

226-226: Improved caching strategy for game-lobby route.

Changing the route rule for "/game-lobby" from { ssr: false } to { swr: true } is a good improvement. This enables the Stale-While-Revalidate caching strategy, which can enhance performance by serving cached content quickly while updating it in the background.

Consider applying this strategy to other suitable routes if you haven't already, to further improve the application's overall performance and user experience.

tests/unit/specs/pages/game-lobby/game-lobby.nuxt.spec.ts (3)

Line range hint 134-152: Consider adjusting the small screen detection test

The current test for small screen detection uses vi.advanceTimersByTime(200) to simulate the 200ms delay. While this works, it might be more robust to use vi.runAllTimers() instead. This ensures that all timers are executed, regardless of the specific timeout value, making the test less brittle to changes in the delay time.

Additionally, consider adding a test case where the screen size changes from large to small after the component is mounted. This would ensure that the component reacts correctly to dynamic changes in screen size.


Line range hint 225-232: Enhance error handling tests

The error handling tests are good, but they could be more robust. Consider the following improvements:

  1. Test the exact error message: Instead of just checking if createError was called, assert that it was called with the correct error message.

  2. Test error propagation: Ensure that the error is actually thrown and not just created. You can do this by wrapping the error-causing code in a try-catch block and asserting that the correct error is caught.

  3. Consider adding tests for error recovery: If there are any mechanisms in place to recover from these errors, add tests to verify they work as expected.

Example improvement for one of the error tests:

it("should throw error when game lobby players party emits pick role for player event but the role picker is not found in refs.", async() => {
  wrapper = await mountGameLobbyPageComponent();
  (wrapper.vm.$root?.$refs.VTU_COMPONENT as { gameLobbyRolePicker: Ref }).gameLobbyRolePicker.value = null;
  const gameLobbyPlayersParty = wrapper.findComponent<typeof GameLobbyPlayersParty>("#game-lobby-players-party");
  
  await expect(async () => {
    await (gameLobbyPlayersParty.vm as VueVm).$emit("pick-role-for-player", createFakeCreateGamePlayerDto());
  }).rejects.toThrow("Game Lobby Role Picker is not defined");

  expect(createError).toHaveBeenCalledExactlyOnceWith("Game Lobby Role Picker is not defined");
});

Also applies to: 268-275, 311-318, 354-361, 397-404


Line range hint 453-474: Improve inject player from query tests

The tests for injecting players from the query are good, but they could be more comprehensive. Consider adding the following test cases:

  1. Test with an empty array of player names.
  2. Test with a very large number of player names to ensure there's no upper limit issue.
  3. Test with player names containing special characters or very long names.
  4. Test the behavior when some names in the array are empty strings or null.

Example additional test:

it("should handle empty strings and null values in player names array", async() => {
  hoistedMocks.useRoute.query = { playerNames: ["Antoine", "", null, "Corentin"] };
  wrapper = await mountGameLobbyPageComponent();
  const createGameDtoStore = useCreateGameDtoStore();

  expect(createGameDtoStore.setPlayersToCreateGameDto).toHaveBeenCalledExactlyOnceWith([
    createFakeCreateGamePlayerDto({ name: "Antoine" }),
    createFakeCreateGamePlayerDto({ name: "Corentin" }),
  ]);
});

This will ensure that the function handles various edge cases correctly.

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 31ab282 and 42b783d.

📒 Files selected for processing (6)
  • app/composables/misc/useDevice.ts (1 hunks)
  • app/pages/game-lobby.vue (1 hunks)
  • config/eslint/flat-configs/eslint.global-config.mjs (1 hunks)
  • nuxt.config.ts (2 hunks)
  • tests/unit/specs/composables/misc/useDevice.spec.ts (1 hunks)
  • tests/unit/specs/pages/game-lobby/game-lobby.nuxt.spec.ts (1 hunks)
🧰 Additional context used
🔇 Additional comments (7)
tests/unit/specs/composables/misc/useDevice.spec.ts (2)

Line range hint 1-43: Overall, good improvements with some suggestions for refinement

The changes to this test file are generally positive:

  1. The new test case for handling undefined window object improves coverage and aligns with the PR objectives.
  2. Existing tests remain intact, maintaining previous functionality.

However, there are opportunities for improvement:

  1. Enhance test isolation, particularly when modifying global objects.
  2. Consider the implications of removing the afterAll hook.
  3. Look into reducing the need for eslint-disable comments.

These refinements would further improve the robustness and maintainability of the test suite. Despite these suggestions, the current changes do enhance the test coverage and are a step in the right direction.


Line range hint 1-43: Consider the implications of removing the afterAll hook

The removal of the afterAll hook that previously deleted the window.ontouchstart property might have some implications:

  1. It could potentially leave the window.ontouchstart property modified after this test suite runs, which might affect other tests or parts of the application that rely on this property.

  2. The beforeEach hook is still in place, which resets the environment before each test within this suite. This ensures that each test within the suite starts with a clean slate.

  3. The removal might be intentional to allow for a more persistent touch-enabled environment in other tests or parts of the application.

To ensure this change doesn't have unintended consequences, please verify:

  1. That no other test suites or parts of the application rely on the window.ontouchstart property being unset after these tests run.
  2. That the persistent window.ontouchstart property (if any) doesn't interfere with other touch-related tests or functionalities.

You can use the following script to check for other occurrences of window.ontouchstart in the test files:

If there are other occurrences, consider whether they need to be updated or if a global setup/teardown for touch-related tests would be beneficial.

✅ Verification successful

Verification Complete: No Issues Found

After reviewing the use of window.ontouchstart across the test files, it appears that:

  • The removal of the afterAll hook does not affect other test suites.
  • The existing beforeEach hook ensures that each test maintains a consistent environment by resetting window.ontouchstart.
  • No other tests modify or rely on window.ontouchstart, mitigating potential side effects.
🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for other occurrences of window.ontouchstart in test files
rg --type ts 'window\.ontouchstart' tests/

Length of output: 230

nuxt.config.ts (1)

77-77: Please clarify the reason for disabling buildCache.

The experimental buildCache has been set to false. While this might resolve certain development issues, it could potentially increase build times. Could you provide more context on why this change was necessary?

To understand the impact, let's check if there are any related comments or issues:

app/pages/game-lobby.vue (1)

30-42: Approve the use of ClientOnly wrapper for client-side rendering.

The introduction of the ClientOnly wrapper for these game lobby components is a good practice. It ensures that components that likely rely on client-side APIs or browser-specific features are only rendered on the client, preventing potential hydration mismatches.

However, be aware of the following implications:

  1. These components will only render after the client-side JavaScript is loaded and executed, which may cause a slight delay in their appearance.
  2. Content within these components won't be available for server-side rendering, which could impact SEO if any critical content is included.

Given that these components seem to be related to game setup and management, the use of ClientOnly is justified and should improve the overall stability of the application.

config/eslint/flat-configs/eslint.global-config.mjs (1)

9-9: LGTM! Verify if this addition is necessary for your project.

The addition of global: READONLY to the globals object is consistent with other global variable declarations in this configuration. This change allows the use of the global object in your codebase without ESLint warnings, while preventing accidental assignments to it.

To ensure this addition is necessary, you can run the following command to check for usage of the global object in your project:

If there are no results or only a few specific use cases, consider if this global declaration is needed.

✅ Verification successful

To resolve the issue with the previous script, please use the following command to search for the usage of the global object in your project:


Verified: The addition of global: READONLY is unnecessary as the global object is not used in the codebase.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Search for usage of the global object in the project
rg '\bglobal\b' --type js --type vue --type ts

Length of output: 76


Script:

#!/bin/bash
# Search for usage of the global object in the project across JS, TS, and Vue files
rg '\bglobal\b' --type js --type ts -g '*.vue'

Length of output: 48

tests/unit/specs/pages/game-lobby/game-lobby.nuxt.spec.ts (2)

89-89: LGTM: Addition of ClientOnly stub

The addition of the ClientOnly: false stub in the mountGameLobbyPageComponent function is a good practice. This ensures that components wrapped with ClientOnly in the actual component are properly rendered during tests, maintaining consistency between the test environment and the real application behavior.


Line range hint 1-474: Overall, the test suite is comprehensive and well-structured

The test file for the Game Lobby page is thorough and covers a wide range of scenarios, including component interactions, error handling, and various edge cases. The addition of the ClientOnly stub is a good practice for ensuring consistent behavior between tests and the actual application.

To further improve the test suite, consider:

  1. Refining the small screen detection test for more robustness.
  2. Enhancing error handling tests to check for specific error messages and error propagation.
  3. Expanding the inject player from query tests to cover more edge cases.

These improvements will make the test suite even more robust and help catch potential issues early in the development process.

tests/unit/specs/composables/misc/useDevice.spec.ts Outdated Show resolved Hide resolved
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

🧹 Outside diff range and nitpick comments (7)
tests/unit/specs/stores/local-storage/useLocalStorageStore.nuxt.spec.ts (2)

9-16: LGTM: Effective mocking setup with a minor suggestion.

The use of vi.hoisted for mocking useLocalStorage is a good practice for performance in Vitest. The mock setup allows for controlled testing of useLocalStorage behavior, and the spread operator ensures other imports from @vueuse/core are preserved.

Consider adding a type annotation to the mock function for improved type safety:

useLocalStorage: vi.fn<Parameters<typeof useLocalStorage>, ReturnType<typeof useLocalStorage>>(() => ({})),

23-34: LGTM: Well-structured test cases with a suggestion for improvement.

The test cases effectively verify the initialization of game options and audio settings in the useLocalStorageStore. The use of toHaveBeenCalledWith is appropriate for checking function calls, and expect.any(Object) provides flexibility for the audio settings default value.

Consider adding the following improvements:

  1. Test the return value of useLocalStorageStore to ensure it contains the expected properties.
  2. Add a test case for updating values in the store to ensure reactivity.

Example:

it("should return a store with expected properties", () => {
  const store = useLocalStorageStore();
  expect(store).toHaveProperty('gameOptions');
  expect(store).toHaveProperty('audioSettings');
});

it("should update stored values when modified", () => {
  const store = useLocalStorageStore();
  store.gameOptions.someOption = 'newValue';
  expect(hoistedMocks.useLocalStorage).toHaveBeenCalledWith(
    LocalStorageKeys.GAME_OPTIONS,
    expect.objectContaining({ someOption: 'newValue' }),
    { mergeDefaults: true }
  );
});
app/components/pages/game-lobby/GameLobbyHeader/GameLobbyHeaderSetupButtons/GameLobbyHeaderOptionsButton/GameLobbyHeaderOptionsButton.vue (1)

20-29: Approve the use of ClientOnly wrapper with a minor suggestion

The addition of the ClientOnly wrapper around the PrimeVueBadge component is a good practice for preventing hydration mismatches in SSR applications. This ensures that the badge is only rendered on the client-side, which can be beneficial for components that rely on client-side state or browser APIs.

However, consider the following:

  1. This change might cause a slight visual shift after the initial page load, as the badge will only appear after client-side hydration.
  2. To mitigate this, you could consider adding a placeholder with the same dimensions as the badge to prevent layout shifts.

If you want to prevent potential layout shifts, you could add a placeholder div with the same dimensions as the badge. Here's an example:

<ClientOnly>
  <template #fallback>
    <div class="inline-block w-5 h-5"></div>
  </template>
  <PrimeVueBadge
    v-if="changedGameOptionsCount"
    id="changed-game-options-count-badge"
    v-p-tooltip="changedGameOptionsBadgeTooltip"
    data-testid="changed-game-options-count-badge"
    severity="secondary"
    :value="changedGameOptionsCount"
  />
</ClientOnly>

This ensures that there's always a space reserved for the badge, whether it's rendered or not.

app/stores/game/create-game-dto/useCreateGameDtoStore.ts (1)

Line range hint 82-92: Good update to resetCreateGameDto, with a minor suggestion.

The use of createGameOptionsDtoFromLocalStorage.value in resetCreateGameDto ensures consistency with the local storage state when resetting. This is a good improvement.

Consider renaming the doesRetrieveLocalStorageValues parameter to useLocalStorageValues for better clarity:

-function resetCreateGameDto(doesRetrieveLocalStorageValues = true): void {
-  if (!doesRetrieveLocalStorageValues) {
+function resetCreateGameDto(useLocalStorageValues = true): void {
+  if (!useLocalStorageValues) {

This small change would make the function's behavior more immediately clear to other developers.

tests/unit/specs/stores/audio/useAudioStore.spec.ts (1)

1-1: LGTM! Consider adding type annotation for useLocalStorageStore mock.

The changes to the import statements and mock setup look good. The addition of the Howler type import and the restructuring of the useLocalStorageStore mock improve type safety and better reflect the actual store structure.

Consider adding a type annotation to the useLocalStorageStore mock to further improve type safety:

useLocalStorageStore: vi.fn(() => ({
  audioSettingsFromLocalStorage: {
    value: {} as AudioSettings,
  },
})),

Also applies to: 23-27, 38-39

tests/unit/specs/stores/game/create-game-dto/useCreateGameDtoStore.spec.ts (2)

128-128: Assertions updated to match new local storage structure

The test assertions have been correctly updated to use createGameOptionsDtoFromLocalStorage, aligning with the new local storage store structure. This ensures that the tests accurately verify the behavior of the useCreateGameDtoStore composable.

For consistency, consider using a constant for the property name createGameOptionsDtoFromLocalStorage throughout the test file. This would make future updates easier if the property name changes.

Also applies to: 281-281, 301-301, 324-324


249-249: Mock setup in individual tests aligned with new structure

The updates to individual test setups correctly use the new mock structure for local storage. This maintains the integrity of the tests and ensures they accurately reflect the expected behavior of the composable.

To improve readability and reduce duplication, consider creating a helper function for setting up the local storage mock with specific values. This could be especially useful if more tests need to set up custom local storage states in the future.

Also applies to: 269-269

📜 Review details

Configuration used: .coderabbit.yaml
Review profile: CHILL

📥 Commits

Files that changed from the base of the PR and between 42b783d and 85e95f4.

📒 Files selected for processing (10)
  • app/components/pages/game-lobby/GameLobbyHeader/GameLobbyHeaderSetupButtons/GameLobbyHeaderOptionsButton/GameLobbyHeaderOptionsButton.vue (1 hunks)
  • app/stores/audio/useAudioStore.ts (1 hunks)
  • app/stores/enums/store.enum.ts (1 hunks)
  • app/stores/game/create-game-dto/useCreateGameDtoStore.ts (1 hunks)
  • app/stores/local-storage/useLocalStorageStore.ts (1 hunks)
  • tests/unit/specs/components/pages/game-lobby/GameLobbyHeader/GameLobbyHeaderSetupButtons/GameLobbyHeaderOptionsButton/GameLobbyHeaderOptionsButton.nuxt.spec.ts (2 hunks)
  • tests/unit/specs/composables/misc/useDevice.spec.ts (2 hunks)
  • tests/unit/specs/stores/audio/useAudioStore.spec.ts (4 hunks)
  • tests/unit/specs/stores/game/create-game-dto/useCreateGameDtoStore.spec.ts (7 hunks)
  • tests/unit/specs/stores/local-storage/useLocalStorageStore.nuxt.spec.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • tests/unit/specs/composables/misc/useDevice.spec.ts
🧰 Additional context used
🔇 Additional comments (29)
app/stores/enums/store.enum.ts (1)

10-10: LGTM! Consider documenting the purpose of this new store.

The addition of LOCAL_STORAGE = "localStorage" to the StoreIds enum is consistent with the existing entries in terms of naming convention and structure. This new entry likely indicates the introduction of a new store for managing local storage operations.

Consider adding a brief comment above the enum or this specific entry to document the purpose of this new store. This would help other developers understand its intended use within the application.

To ensure this change doesn't introduce any inconsistencies, let's verify its usage across the codebase:

This script will help us identify where the new store ID is being used and ensure it's implemented consistently across the application.

✅ Verification successful

Verified the usage of StoreIds.LOCAL_STORAGE across the codebase.

The entry LOCAL_STORAGE = "localStorage" is correctly implemented in useLocalStorageStore.ts and aligns with the existing naming conventions.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for usage of the new LOCAL_STORAGE store ID

# Search for direct usage of StoreIds.LOCAL_STORAGE
echo "Searching for direct usage of StoreIds.LOCAL_STORAGE:"
rg --type typescript "StoreIds\.LOCAL_STORAGE"

# Search for string literal "localStorage" in store-related files
echo "Searching for 'localStorage' string in store-related files:"
rg --type typescript "'localStorage'" app/stores

Length of output: 427


Script:

#!/bin/bash
# Description: Check for usage of the new LOCAL_STORAGE store ID with corrected file type

# Search for direct usage of StoreIds.LOCAL_STORAGE
echo "Searching for direct usage of StoreIds.LOCAL_STORAGE:"
rg --type ts "StoreIds\.LOCAL_STORAGE"

# Search for string literal "localStorage" in store-related files
echo "Searching for 'localStorage' string in store-related files:"
rg --type ts "'localStorage'" app/stores

Length of output: 463

app/stores/local-storage/useLocalStorageStore.ts (5)

1-3: LGTM: Imports are correctly defined and used.

The necessary imports from '@vueuse/core' and 'pinia' are properly included for the store's functionality.


4-8: Well-structured imports with good use of constants.

The imports for default constants, types, and enums are well-organized. Using constants for default values (DEFAULT_GAME_OPTIONS and DEFAULT_AUDIO_SETTINGS) is a good practice as it enhances maintainability and reduces the risk of errors.


10-23: Excellent store definition with proper use of local storage and SSR considerations.

The store is well-defined using Pinia's composition API style, which is great for type inference and composability. Notable good practices:

  1. Utilization of useLocalStorage for persistent data storage.
  2. Enabling mergeDefaults option to ensure new fields in default objects are added to existing stored data.
  3. Wrapping properties with skipHydrate to prevent hydration mismatches in SSR applications.

These practices contribute to a robust and maintainable store implementation.


25-25: LGTM: Proper export of the store.

The store is correctly exported as a named export, following best practices for module exports in TypeScript.


1-25: Excellent implementation of a local storage store using Pinia and Vue 3 best practices.

This new file introduces a well-structured Pinia store for managing local storage, specifically handling game options and audio settings. The implementation showcases several best practices:

  1. Proper use of Vue 3 and Pinia APIs.
  2. Effective management of local storage using useLocalStorage from VueUse.
  3. Consideration for SSR scenarios by using skipHydrate.
  4. Good use of TypeScript for type safety.
  5. Clean and readable code structure.

The store provides a solid foundation for managing persistent data in the application. Great job on the implementation!

tests/unit/specs/stores/local-storage/useLocalStorageStore.nuxt.spec.ts (2)

1-8: LGTM: Imports and constants are well-organized.

The imports are appropriate for the testing setup, including Pinia for state management, Vitest for testing, and project-specific constants. The use of type import for VueUse is a good practice for maintaining type safety.


18-21: LGTM: Proper test suite setup.

The test suite is well-structured with a describe block to group related tests. The beforeEach hook correctly sets up a fresh Pinia instance before each test, ensuring a clean state for each test case. This is a good practice for maintaining test isolation.

app/components/pages/game-lobby/GameLobbyHeader/GameLobbyHeaderSetupButtons/GameLobbyHeaderOptionsButton/GameLobbyHeaderOptionsButton.vue (2)

Line range hint 31-67: Script section aligns well with template changes

The script section of the component is well-structured and aligns perfectly with the template changes:

  1. The changedGameOptionsCount computed property is correctly used in the template's v-if condition for the badge.
  2. The changedGameOptionsBadgeTooltip computed property is properly utilized in the badge's v-p-tooltip directive.
  3. The click handler onClickFromGameOptionsButton is correctly bound to the button's click event.

The use of the Composition API with <script setup> promotes a clean and maintainable code structure. The component's logic, including the use of Pinia store and computed properties, is implemented effectively.


Line range hint 1-67: Summary: Improved SSR compatibility with minimal changes

The changes made to this component are minimal yet impactful:

  1. The addition of the ClientOnly wrapper around the PrimeVueBadge improves SSR compatibility by ensuring the badge is only rendered on the client-side.
  2. The core functionality and structure of the component remain unchanged, maintaining its original behavior.

These changes demonstrate a thoughtful approach to addressing potential SSR-related issues without introducing significant alterations to the component's logic or user experience.

app/stores/audio/useAudioStore.ts (4)

2-2: LGTM: Import statements updated to reflect new local storage handling.

The changes in the import statements correctly reflect the shift from using @vueuse/core's useLocalStorage to a custom useLocalStorageStore. This approach centralizes local storage management, which can improve maintainability and consistency across the application.

Also applies to: 6-7, 9-9


12-13: LGTM: Improved local storage handling with centralized store.

The implementation of useLocalStorageStore and the use of storeToRefs to access audioSettingsFromLocalStorage is a solid improvement. This approach:

  1. Centralizes local storage logic, improving maintainability.
  2. Maintains reactivity through storeToRefs, ensuring that changes are properly tracked and propagated.
  3. Enhances the separation of concerns within the application architecture.

Line range hint 1-124: Overall: Excellent refactoring of local storage handling in the audio store.

The changes made to useAudioStore represent a significant improvement in how local storage is managed for audio settings. By centralizing local storage logic in a separate store and using storeToRefs, the code becomes more maintainable and consistent. This refactoring:

  1. Improves separation of concerns
  2. Enhances reactivity and state management
  3. Maintains the existing functionality while setting up a more scalable structure

These changes align well with best practices in Vue and Pinia state management.


Line range hint 98-98: LGTM: setMute function updated to use new local storage mechanism.

The setMute function has been correctly updated to use audioSettingsFromLocalStorage.value.isMuted, which aligns with the new centralized local storage handling approach. This change ensures that mute state changes are consistently reflected across the application and persisted correctly.

To ensure this change is consistent throughout the codebase, let's verify that no direct local storage access for audio settings remains:

✅ Verification successful

To ensure that no direct localStorage access for audio settings remains, please run the following updated scripts:


No direct localStorage access for audio settings found outside of test files.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Check for any remaining direct local storage access for audio settings

# Test: Search for direct localStorage access related to audio settings
rg --type typescript 'localStorage.*audio'

# Test: Search for useLocalStorage hook usage related to audio
rg --type typescript 'useLocalStorage.*audio'

Length of output: 162


Script:

#!/bin/bash
# Description: Check for any remaining direct local storage access for audio settings

# Test: Search for direct localStorage access related to audio settings in TypeScript files
rg --type ts 'localStorage.*audio'

# Test: Search for useLocalStorage hook usage related to audio in TypeScript files
rg --type ts 'useLocalStorage.*audio'

Length of output: 408

tests/unit/specs/components/pages/game-lobby/GameLobbyHeader/GameLobbyHeaderSetupButtons/GameLobbyHeaderOptionsButton/GameLobbyHeaderOptionsButton.nuxt.spec.ts (3)

32-32: LGTM: Addition of ClientOnly stub

The addition of the ClientOnly stub set to false in the global configuration is appropriate. This ensures that the component wrapped in ClientOnly is rendered during unit tests, which is consistent with best practices for testing Nuxt components.


94-94: LGTM: Consistent application of ClientOnly stub

The addition of the ClientOnly stub (set to false) in this test case is consistent with the earlier change. This ensures that the component is properly rendered when testing the tooltip functionality, maintaining consistency across different test scenarios.


Line range hint 1-118: Overall assessment: Well-implemented changes for ClientOnly integration

The changes in this test file are consistent and well-implemented. They effectively address the integration of the ClientOnly component in the test environment, which aligns with the likely changes in the actual component implementation. The consistent application of the ClientOnly stub across different test scenarios ensures comprehensive coverage and maintains the integrity of the tests.

app/stores/game/create-game-dto/useCreateGameDtoStore.ts (5)

1-1: LGTM: Import changes are appropriate.

The changes to the import statements are consistent with the refactoring of local storage handling and the use of storeToRefs. These modifications improve the organization and maintainability of the code.

Also applies to: 9-9, 17-17


24-25: Great improvement in local storage management.

The use of useLocalStorageStore and storeToRefs centralizes local storage management and ensures reactivity. This change aligns with Pinia's best practices for cross-store interactions, improving the overall architecture of the application.


Line range hint 27-35: Improved initialization of createGameDto.

The use of createGameOptionsDtoFromLocalStorage.value in the initialization of createGameDto ensures that the game options are correctly loaded from local storage. This change maintains consistency between the local storage and the store state, providing a more reliable initial state for the game creation process.


Line range hint 103-105: Excellent simplification of local storage saving.

The saveCreateGameOptionsDtoToLocalStorage function has been streamlined to directly assign to createGameOptionsDtoFromLocalStorage.value. This change leverages Pinia's reactivity system effectively, ensuring that updates to game options are properly tracked and persisted. The simplicity of this implementation reduces the chances of errors and improves maintainability.


Line range hint 1-238: Overall excellent refactoring of local storage management.

The changes in this file significantly improve the management of game options in local storage. By leveraging Pinia's storeToRefs and centralizing local storage operations, the code becomes more maintainable and consistent. These modifications enhance the reliability of the game creation process and align well with Vue 3 and Pinia best practices.

Key improvements:

  1. Centralized local storage management using useLocalStorageStore.
  2. Improved reactivity with storeToRefs.
  3. Consistent initialization and resetting of game options.
  4. Simplified saving of game options to local storage.

These changes contribute to a more robust and efficient implementation of the create game DTO store.

tests/unit/specs/stores/audio/useAudioStore.spec.ts (4)

45-45: LGTM! Improved test setup with DEFAULT_AUDIO_SETTINGS.

The update to the beforeEach setup ensures that audioSettingsFromLocalStorage is initialized with DEFAULT_AUDIO_SETTINGS. This change provides a consistent and realistic initial state for the tests, aligning well with the updated mock structure.


Line range hint 1-305: Clarify testing of audio settings initialization.

I noticed that the test case for setting audio settings from local storage upon creation has been removed. While this aligns with the updates to the mock structure and beforeEach setup, it's important to ensure that the initialization of audio settings is still properly tested.

Could you please clarify how the initialization of audio settings from local storage is now being tested? If it's tested elsewhere, please provide the location. If it's no longer necessary, please explain why.

To help investigate this, you can run the following script to search for relevant test cases:

#!/bin/bash
# Description: Search for tests related to audio settings initialization

# Test: Search for test cases involving audioSettingsFromLocalStorage
rg --type typescript 'audioSettingsFromLocalStorage' 'tests/unit/specs'

Line range hint 1-305: LGTM! Consider verifying test coverage metrics.

The test suite provides comprehensive coverage of the audio store's functionality, including initial state, audio loading, playing sound effects and background audio, muting, and more. The changes made to the tests appropriately reflect updates in the store's implementation and structure.

To ensure that the test coverage remains high after these changes, consider running a test coverage tool and verifying the metrics. You can use a script like this to generate a coverage report:

#!/bin/bash
# Description: Generate test coverage report for the audio store

# Test: Run tests with coverage for the audio store
npx vitest run --coverage stores/audio/useAudioStore.ts

Please review the coverage report and ensure that all critical paths in the audio store are adequately tested.


290-290: LGTM! Verify corresponding changes in the main code.

The updated assertion for audioSettingsFromLocalStorage correctly reflects the simplified structure of the audio settings object. This change aligns well with the updated mock structure.

To ensure consistency, please verify that the corresponding changes have been made in the main code. Run the following script to check the implementation of setMute in the audio store:

✅ Verification successful

Verification Successful!

The implementation of the setMute function in app/stores/audio/useAudioStore.ts aligns with the updated test assertion. No issues found.

🏁 Scripts executed

The following scripts were executed for the analysis:

Script:

#!/bin/bash
# Description: Verify the implementation of setMute in the audio store

# Test: Search for the setMute function in the audio store
rg --type typescript 'setMute.*=' -A 10 'stores/audio/useAudioStore.ts'

Length of output: 222


Script:

#!/bin/bash
# Description: Verify the implementation of setMute in the audio store

# Test: Search for the setMute function in the audio store
rg --type typescript 'function\s+setMute\s*\(' 'stores/audio/useAudioStore.ts' -A 10

Length of output: 119


Script:

#!/bin/bash
# Description: Verify the implementation of setMute in the audio store

# Test: Search for the setMute function in the audio store
rg 'function\s+setMute\s*\(' 'stores/audio/useAudioStore.ts' -A 10

Length of output: 136


Script:

#!/bin/bash
# Description: Search for the setMute function across the entire codebase

# Test: Search for the setMute function in all TypeScript files
rg 'function\s+setMute\s*\(' --type ts -A 10

Length of output: 715

tests/unit/specs/stores/game/create-game-dto/useCreateGameDtoStore.spec.ts (3)

19-28: Improved local storage mocking structure

The change from mocking @vueuse/core to ~/stores/local-storage/useLocalStorageStore.ts is a good improvement. It centralizes local storage operations into a dedicated store, which enhances organization and potential reusability across the application.


34-34: LGTM: Consistent test setup with new local storage mock

The update to the beforeEach hook ensures that each test starts with a clean state using the new local storage store structure. This is a good practice for maintaining consistent and reliable tests.


Line range hint 1-1004: Overall: Improved local storage handling and test structure

The changes in this file consistently update the local storage mocking to use a centralized store approach. This improves code organization and potential reusability. All test cases and assertions have been carefully updated to work with the new structure, maintaining good test coverage and accuracy.

The modifications enhance the maintainability of the tests and reflect good practices in terms of centralized state management and consistent mocking strategies.

Copy link

sonarcloud bot commented Oct 13, 2024

@antoinezanardi antoinezanardi merged commit 252edcd into develop Oct 13, 2024
19 checks passed
@antoinezanardi antoinezanardi deleted the feat/game-lobby-swr branch October 13, 2024 20:40
antoinezanardi pushed a commit that referenced this pull request Oct 14, 2024
## [1.34.0](v1.33.0...v1.34.0) (2024-10-14)

### 🚀 Features

* **font:** use nuxt font instead of google plugin ([#970](#970)) ([31ab282](31ab282))
* **game-lobby:** generation on server at demand ([#971](#971)) ([252edcd](252edcd))
* **game:** game feedback submitter ([#969](#969)) ([a6458dd](a6458dd))

### ⚡️ Performances

* **game:** player groups in game from api ([#956](#956)) ([766856e](766856e))

### 🧹 Chore

* **deps:** update antoinezanardi/werewolves-assistant-api docker tag to v1.37.0 ([#951](#951)) ([79eb7a0](79eb7a0))
* **deps:** update dependency @nuxt/devtools to ^1.5.2 ([#939](#939)) ([ef565b8](ef565b8))
* **deps:** update dependency @nuxt/devtools to ^1.6.0 ([#968](#968)) ([672df78](672df78))
* **deps:** update dependency @nuxt/image to ^1.8.1 ([#941](#941)) ([aa8a7ce](aa8a7ce))
* **deps:** update dependency @nuxt/test-utils to ^3.14.3 ([#953](#953)) ([fa793a9](fa793a9))
* **deps:** update dependency @primevue/nuxt-module to ^4.1.0 ([#955](#955)) ([758fa27](758fa27))
* **deps:** update dependency @stylistic/eslint-plugin to ^2.9.0 ([#950](#950)) ([1b93cdc](1b93cdc))
* **deps:** update dependency @vitest/eslint-plugin to ^1.1.5 ([#942](#942)) ([26a84dc](26a84dc))
* **deps:** update dependency @vitest/eslint-plugin to ^1.1.6 ([#948](#948)) ([d950878](d950878))
* **deps:** update dependency @vitest/eslint-plugin to ^1.1.7 ([#960](#960)) ([1a66522](1a66522))
* **deps:** update dependency eslint to ^9.12.0 ([#949](#949)) ([8fd12ae](8fd12ae))
* **deps:** update dependency eslint-plugin-import to ^2.31.0 ([#944](#944)) ([2b10420](2b10420))
* **deps:** update dependency eslint-plugin-vue to ^9.29.0 ([#966](#966)) ([3611a44](3611a44))
* **deps:** update dependency msw to ^2.4.10 ([#965](#965)) ([0feb24b](0feb24b))
* **deps:** update dependency msw to ^2.4.11 ([#972](#972)) ([eb488fc](eb488fc))
* **deps:** update dependency ofetch to ^1.4.1 ([#962](#962)) ([07f7ca7](07f7ca7))
* **deps:** update dependency sass to ^1.79.5 ([#964](#964)) ([0a683aa](0a683aa))
* **deps:** update dependency typescript to ^5.6.3 ([#963](#963)) ([7bdc97d](7bdc97d))
* **deps:** update dependency vue to ^3.5.11 ([#945](#945)) ([582287a](582287a))
* **deps:** update dependency vue to ^3.5.12 ([#967](#967)) ([54641ff](54641ff))
* **deps:** update dependency vue-ellipse-progress to ^2.2.0 ([#946](#946)) ([3cd48c2](3cd48c2))
* **deps:** update node.js to >=20.18.0 ([#947](#947)) ([26b6311](26b6311))
* **deps:** update playwright monorepo to ^1.48.0 ([#961](#961)) ([c676c68](c676c68))
* **deps:** update pnpm to v9.12.0 ([#938](#938)) ([48aaaab](48aaaab))
* **deps:** update pnpm to v9.12.1 ([#954](#954)) ([452305c](452305c))
* **deps:** update typescript-eslint monorepo to ^8.8.1 ([#959](#959)) ([c550664](c550664))
* **deps:** update vitest monorepo to ^2.1.2 ([#940](#940)) ([672d869](672d869))
* **eslint:** import plugin is back ([#952](#952)) ([a5a4673](a5a4673))
* **merge:** from main ([d29a383](d29a383))
@antoinezanardi
Copy link
Owner Author

🎉 This PR is included in version 1.34.0 🎉

The release is available on GitHub release

Your semantic-release bot 📦🚀

antoinezanardi pushed a commit that referenced this pull request Oct 14, 2024
## [1.34.0](v1.33.0...v1.34.0) (2024-10-14)

### 🚀 Features

* **font:** use nuxt font instead of google plugin ([#970](#970)) ([31ab282](31ab282))
* **game-lobby:** generation on server at demand ([#971](#971)) ([252edcd](252edcd))
* **game:** game feedback submitter ([#969](#969)) ([a6458dd](a6458dd))

### ⚡️ Performances

* **game:** player groups in game from api ([#956](#956)) ([766856e](766856e))

### 🧹 Chore

* **deps:** update antoinezanardi/werewolves-assistant-api docker tag to v1.37.0 ([#951](#951)) ([79eb7a0](79eb7a0))
* **deps:** update dependency @nuxt/devtools to ^1.5.2 ([#939](#939)) ([ef565b8](ef565b8))
* **deps:** update dependency @nuxt/devtools to ^1.6.0 ([#968](#968)) ([672df78](672df78))
* **deps:** update dependency @nuxt/image to ^1.8.1 ([#941](#941)) ([aa8a7ce](aa8a7ce))
* **deps:** update dependency @nuxt/test-utils to ^3.14.3 ([#953](#953)) ([fa793a9](fa793a9))
* **deps:** update dependency @primevue/nuxt-module to ^4.1.0 ([#955](#955)) ([758fa27](758fa27))
* **deps:** update dependency @stylistic/eslint-plugin to ^2.9.0 ([#950](#950)) ([1b93cdc](1b93cdc))
* **deps:** update dependency @vitest/eslint-plugin to ^1.1.5 ([#942](#942)) ([26a84dc](26a84dc))
* **deps:** update dependency @vitest/eslint-plugin to ^1.1.6 ([#948](#948)) ([d950878](d950878))
* **deps:** update dependency @vitest/eslint-plugin to ^1.1.7 ([#960](#960)) ([1a66522](1a66522))
* **deps:** update dependency eslint to ^9.12.0 ([#949](#949)) ([8fd12ae](8fd12ae))
* **deps:** update dependency eslint-plugin-import to ^2.31.0 ([#944](#944)) ([2b10420](2b10420))
* **deps:** update dependency eslint-plugin-vue to ^9.29.0 ([#966](#966)) ([3611a44](3611a44))
* **deps:** update dependency msw to ^2.4.10 ([#965](#965)) ([0feb24b](0feb24b))
* **deps:** update dependency msw to ^2.4.11 ([#972](#972)) ([eb488fc](eb488fc))
* **deps:** update dependency ofetch to ^1.4.1 ([#962](#962)) ([07f7ca7](07f7ca7))
* **deps:** update dependency sass to ^1.79.5 ([#964](#964)) ([0a683aa](0a683aa))
* **deps:** update dependency typescript to ^5.6.3 ([#963](#963)) ([7bdc97d](7bdc97d))
* **deps:** update dependency vue to ^3.5.11 ([#945](#945)) ([582287a](582287a))
* **deps:** update dependency vue to ^3.5.12 ([#967](#967)) ([54641ff](54641ff))
* **deps:** update dependency vue-ellipse-progress to ^2.2.0 ([#946](#946)) ([3cd48c2](3cd48c2))
* **deps:** update node.js to >=20.18.0 ([#947](#947)) ([26b6311](26b6311))
* **deps:** update playwright monorepo to ^1.48.0 ([#961](#961)) ([c676c68](c676c68))
* **deps:** update pnpm to v9.12.0 ([#938](#938)) ([48aaaab](48aaaab))
* **deps:** update pnpm to v9.12.1 ([#954](#954)) ([452305c](452305c))
* **deps:** update typescript-eslint monorepo to ^8.8.1 ([#959](#959)) ([c550664](c550664))
* **deps:** update vitest monorepo to ^2.1.2 ([#940](#940)) ([672d869](672d869))
* **eslint:** import plugin is back ([#952](#952)) ([a5a4673](a5a4673))
* **merge:** from main ([d29a383](d29a383))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🚀 feature New feature or request released
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant