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

Improve test hygiene and remove Loaded user data… and Saved user data… logging calls #916

Merged
merged 2 commits into from
Feb 11, 2025

Conversation

fredrikekelund
Copy link
Contributor

@fredrikekelund fredrikekelund commented Feb 11, 2025

Related issues

Proposed Changes

This PR does not fix the flaky tests described in https://github.com/Automattic/dotcom-forge/issues/10437, but it addresses a few issues with our tests that I discovered along the way:

  • Silence console output from noisy tests
  • Add relevant mocks to fix warnings
  • Added the __nextHasNoMarginBottom prop to the SelectControl component in src/components/edit-php-version.tsx to silence a console warning
  • Removed Loaded user data… and Saved user data… logging calls (see p1739268087313499-slack-C04GESRBWKW)

Testing Instructions

CI should pass

Pre-merge Checklist

  • Have you checked for TypeScript, React or other console errors?

@fredrikekelund fredrikekelund requested a review from a team February 11, 2025 13:30
@fredrikekelund fredrikekelund self-assigned this Feb 11, 2025
Comment on lines +97 to +101
expect( sendIpcEventToRendererWithWindow ).toHaveBeenCalledWith(
createdWindow,
'window-fullscreen-change',
true
);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Now that we have the sendIpcEventToRendererWithWindow abstraction, it's more fitting to mock that function instead of the underlying BrowserWindow.webContents.send. I hoped this would potentially fix the flaky tests, but it did not.

Comment on lines +49 to +60
// Silence `console.log`, `console.warn`, and `console.error` output
beforeAll( () => {
jest.spyOn( console, 'log' ).mockImplementation( () => {} );
jest.spyOn( console, 'warn' ).mockImplementation( () => {} );
jest.spyOn( console, 'error' ).mockImplementation( () => {} );
} );

afterAll( () => {
jest.spyOn( console, 'log' ).mockRestore();
jest.spyOn( console, 'warn' ).mockRestore();
jest.spyOn( console, 'error' ).mockRestore();
} );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

src/index.ts does a lot of logging to the console. We do this for debugging purposes, but it's just noise in the context of a test runner.

Comment on lines +8 to +10
jest.mock( 'src/storage/user-data', () => ( {
loadUserData: jest.fn().mockResolvedValue( { locale: undefined } ),
} ) );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Without this mock, this test outputs a bunch of warnings like this:

  console.error
    Failed to load file /path/to/app/appData/App Name/appdata-v1.json: Error: ENOENT: no such file or directory, open '/path/to/app/appData/App Name/appdata-v1.json'

      79 | 			};
      80 | 		}
    > 81 | 		console.error( `Failed to load file ${ sanitizeUserpath( filePath ) }: ${ err }` );
         | 		        ^
      82 | 		throw err;
      83 | 	}
      84 | }

      at src/storage/user-data.ts:81:11
          at Generator.throw (<anonymous>)
      at rejected (src/storage/user-data.ts:29:65)

Copy link
Contributor

Choose a reason for hiding this comment

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

Also, maybe let's add it as a comment to code?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair 👍

@@ -74,6 +74,7 @@ export default function EditPhpVersion() {
value: version,
} ) ) }
onChange={ ( version ) => setSelectedPhpVersion( version ) }
__nextHasNoMarginBottom
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've confirmed that this change has no visual impact on the EditPhpVersion component.

Without this prop, this test outputs the following warning:

    console.warn
      Bottom margin styles for wp.components.SelectControl is deprecated since version 6.7 and will be removed in version 7.0. Note: Set the `__nextHasNoMarginBottom` prop to true to start opting into the new styles, which will become the default in a future version.

      at warn (node_modules/@wordpress/components/node_modules/@wordpress/deprecated/build/@wordpress/deprecated/src/index.js:77:10)
      at UnconnectedBaseControl (node_modules/@wordpress/components/build/base-control/@wordpress/components/src/base-control/index.tsx:45:13)
      at renderWithHooks (node_modules/react-dom/cjs/react-dom.development.js:15486:18)
      at mountIndeterminateComponent (node_modules/react-dom/cjs/react-dom.development.js:20103:13)
      at beginWork (node_modules/react-dom/cjs/react-dom.development.js:21626:16)
      at beginWork$1 (node_modules/react-dom/cjs/react-dom.development.js:27465:14)
      at performUnitOfWork (node_modules/react-dom/cjs/react-dom.development.js:26599:12)
      at workLoopSync (node_modules/react-dom/cjs/react-dom.development.js:26505:5)
      at renderRootSync (node_modules/react-dom/cjs/react-dom.development.js:26473:7)
      at performSyncWorkOnRoot (node_modules/react-dom/cjs/react-dom.development.js:26124:20)
      at flushSyncCallbacks (node_modules/react-dom/cjs/react-dom.development.js:12042:22)
      at flushActQueue (node_modules/react/cjs/react.development.js:2667:24)
      at act (node_modules/react/cjs/react.development.js:2582:11)
      at node_modules/@testing-library/react/dist/act-compat.js:47:25
      at Object.eventWrapper (node_modules/@testing-library/react/dist/pure.js:107:28)
      at Object.wrapEvent (node_modules/@testing-library/user-event/dist/cjs/event/wrapEvent.js:6:28)
      at Object.dispatchEvent (node_modules/@testing-library/user-event/dist/cjs/event/dispatchEvent.js:45:22)
      at Object.dispatchUIEvent (node_modules/@testing-library/user-event/dist/cjs/event/dispatchEvent.js:22:26)
      at Mouse.up (node_modules/@testing-library/user-event/dist/cjs/system/pointer/mouse.js:100:30)
      at PointerHost.release (node_modules/@testing-library/user-event/dist/cjs/system/pointer/index.js:84:28)
      at pointerAction (node_modules/@testing-library/user-event/dist/cjs/pointer/index.js:59:47)
      at Object.pointer (node_modules/@testing-library/user-event/dist/cjs/pointer/index.js:32:9)
      at Object.asyncWrapper (node_modules/@testing-library/react/dist/pure.js:88:22)

Comment on lines +10 to +12
jest.mock( 'src/lib/site-language', () => ( {
getPreferredSiteLanguage: jest.fn().mockResolvedValue( 'en' ),
} ) );
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Without this mock, this test outputs the following warning:

  console.error
    An error ocurred when reading translations from '/Users/fredrik/Code/studio/wp-files/latest/available-site-translations.json': SyntaxError: Unexpected end of JSON input
        at JSON.parse (<anonymous>)
        at getLatestVersionTranslations (/Users/fredrik/Code/studio/src/lib/site-language.ts:37:15)
        at /Users/fredrik/Code/studio/src/lib/site-language.ts:63:55
        at Generator.next (<anonymous>)
        at /Users/fredrik/Code/studio/src/lib/site-language.ts:8:71
        at new Promise (<anonymous>)
        at Object.<anonymous>.__awaiter (/Users/fredrik/Code/studio/src/lib/site-language.ts:4:12)
        at getAvailableSiteTranslations (/Users/fredrik/Code/studio/src/lib/site-language.ts:57:12)
        at /Users/fredrik/Code/studio/src/lib/site-language.ts:81:38
        at Generator.next (<anonymous>)
        at /Users/fredrik/Code/studio/src/lib/site-language.ts:8:71
        at new Promise (<anonymous>)
        at Object.<anonymous>.__awaiter (/Users/fredrik/Code/studio/src/lib/site-language.ts:4:12)
        at getPreferredSiteLanguage (/Users/fredrik/Code/studio/src/lib/site-language.ts:76:12)
        at SiteServer.<anonymous> (/Users/fredrik/Code/studio/src/site-server.ts:92:56)
        at Generator.next (<anonymous>)
        at fulfilled (/Users/fredrik/Code/studio/src/site-server.ts:28:58)
        at processTicksAndRejections (node:internal/process/task_queues:95:5)

      37 | 		return JSON.parse( fs.readFileSync( latestVersionTranslationsPath, 'utf8' ) );
      38 | 	} catch ( exception ) {
    > 39 | 		console.error(
         | 		        ^
      40 | 			`An error ocurred when reading translations from '${ latestVersionTranslationsPath }':`,
      41 | 			exception
      42 | 		);

      at getLatestVersionTranslations (src/lib/site-language.ts:39:11)
      at src/lib/site-language.ts:63:55
      at src/lib/site-language.ts:8:71
      at Object.<anonymous>.__awaiter (src/lib/site-language.ts:4:12)
      at getAvailableSiteTranslations (src/lib/site-language.ts:57:12)
      at src/lib/site-language.ts:81:38
      at src/lib/site-language.ts:8:71
      at Object.<anonymous>.__awaiter (src/lib/site-language.ts:4:12)
      at getPreferredSiteLanguage (src/lib/site-language.ts:76:12)
      at SiteServer.<anonymous> (src/site-server.ts:92:56)
      at fulfilled (src/site-server.ts:28:58)

Copy link
Contributor

Choose a reason for hiding this comment

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

WDYT about adding such info as a comment to the code? So that we won't forget and it would be clear why do we have this mock.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fair 👍

Copy link
Contributor

@nightnei nightnei left a comment

Choose a reason for hiding this comment

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

In general it's cool cleaning up 👍
Just left a few comments

Comment on lines +10 to +12
jest.mock( 'src/lib/site-language', () => ( {
getPreferredSiteLanguage: jest.fn().mockResolvedValue( 'en' ),
} ) );
Copy link
Contributor

Choose a reason for hiding this comment

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

WDYT about adding such info as a comment to the code? So that we won't forget and it would be clear why do we have this mock.

@@ -228,7 +228,8 @@ describe( 'chat-slice', () => {
} );

it( 'should handle invalid JSON in localStorage gracefully', () => {
const consoleErrorSpy = jest.spyOn( console, 'error' );
// Silence `console.error` output
const consoleErrorSpy = jest.spyOn( console, 'error' ).mockImplementation( () => {} );
Copy link
Contributor

Choose a reason for hiding this comment

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

Hm, I think it's better to do it in beforeEach / afterEach, to avoid case when this test failed, consoleErrorSpy.mockRestore(); wasn't run and the next test case fails or works incorrectly due to not restoring this spy. WDYT?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That's fair 👍

Comment on lines +8 to +10
jest.mock( 'src/storage/user-data', () => ( {
loadUserData: jest.fn().mockResolvedValue( { locale: undefined } ),
} ) );
Copy link
Contributor

Choose a reason for hiding this comment

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

Also, maybe let's add it as a comment to code?

@@ -57,7 +57,6 @@ export async function loadUserData(): Promise< UserData > {
const data = fromDiskFormat( parsed );
sortSites( data.sites );
populatePhpVersion( data.sites );
console.log( `Loaded user data from ${ sanitizeUserpath( filePath ) }` );
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@@ -98,7 +97,6 @@ export async function saveUserData( data: UserData ): Promise< void > {
await fs.promises.writeFile( filePath, asString, 'utf-8' );
}
}
console.log( `Saved user data to ${ sanitizeUserpath( filePath ) }` );
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

Copy link
Contributor

@nightnei nightnei left a comment

Choose a reason for hiding this comment

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

LGTM 👍

@fredrikekelund fredrikekelund merged commit af558c5 into trunk Feb 11, 2025
7 checks passed
@fredrikekelund fredrikekelund deleted the f26d/test-suite-hygiene branch February 11, 2025 14:22
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