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鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Docs: Improve mocks section for promise-based fs/promises #11136

Closed
thernstig opened this issue Mar 1, 2021 · 11 comments
Closed

Docs: Improve mocks section for promise-based fs/promises #11136

thernstig opened this issue Mar 1, 2021 · 11 comments

Comments

@thernstig
Copy link
Contributor

馃殌 Feature Proposal

https://jestjs.io/docs/en/manual-mocks describes how to mock the 'fs' module. Although good, the latest versions of Node.js 15 puts promise-based version first and fore-most at the top: https://nodejs.org/api/fs.html

It would be cool if https://jestjs.io/docs/en/manual-mocks could describe how to e.g. mock the module require('fs/promises').

Motivation

It would help users moving towards more modern tools such as promised-based versions of e.g. 'fs'.

Example

n/a

Pitch

Because it is a core feature of Jest to mock.

@thernstig
Copy link
Contributor Author

As an examle, mocking current promises can be done like:

const fs = jest.createMockFromModule('fs');

let mockFiles = {};

/**
 * This is a custom function that our tests can use during setup to specify
 * what the files on the "mock" filesystem should look like when any of the
 * `fs` APIs are used.
 *
 * @param {Object} newMockFiles - The keys are the file paths and the values are
 *      the file contents.
 *
 * @example
 * import * as fs from 'fs';
 * jest.mock('fs');
 * const files = {
 *   '/path/to/file1.js': 'console.log("file1 contents");',
 *   '/path/to/file2.txt': 'file2 contents',
 * };
 * fs.setMockFiles(files);
 */
function setMockFiles(newMockFiles) {
  mockFiles = { ...newMockFiles };
}

fs.setMockFiles = setMockFiles;
fs.readFileSync = jest.fn((filePath) => mockFiles[filePath]);

fs.promises = {};
fs.promises.readFile = jest.fn(async (filePath) => mockFiles[filePath]);

module.exports = fs;

But the docs does not explain how to do it when mocking the more modern const fsp = require('fs/promises');
So how would that be achieved and could that be added to the docs?

@SimenB
Copy link
Member

SimenB commented Mar 8, 2021

doesn't jest.mock('fs/promises') work?

Oh, you mean with a manual mock. I never use those, so haven't had the need for one. I guess __mocks__/fs/promises and jest.mock('fs/promises') doesn't work? Since you opened up this issue I mean 馃檪

@thernstig
Copy link
Contributor Author

@SimenB I did not try as I was not sure what to do, and looking at #553 it seems this was not possible. Or maybe they just did not know? Let me try what you say and get back to you!

@thernstig
Copy link
Contributor Author

@SimenB It did work like a charm, like this below. Does it seem functionally correct to you? I wonder if this would be a good addition to the docs somewhere, or would it be too verbose for the docs?

node_modules/
__mocks__/
  fs/
    promises.js
  fs.js
// fs.js

const fs = jest.createMockFromModule('fs');

let mockFiles = {};

/**
 * This is a custom function that our tests can use during setup to specify
 * what the files on the "mock" filesystem should look like when any of the
 * `fs` APIs are used.
 *
 * @param {Object} newMockFiles - The keys are the file paths and the values are
 *      the file contents.
 *
 * @example
 * import * as fs from 'fs';
 * jest.mock('fs');
 * const files = {
 *   '/path/to/file1.js': 'console.log("file1 contents");',
 *   '/path/to/file2.txt': 'file2 contents',
 * };
 * fs.setMockFiles(files);
 */
function setMockFiles(newMockFiles) {
  mockFiles = { ...newMockFiles };
}

/**
 *
 * @returns {Object} The mock files. The keys are the file paths and the values are
 *      the file contents.
 */
function getMockFiles() {
  return mockFiles;
}

fs.setMockFiles = setMockFiles;
fs.getMockFiles = getMockFiles;
fs.readFileSync = jest.fn((filePath) => mockFiles[filePath]);
fs.existsSync = jest.fn((filePath) => filePath in mockFiles);

module.exports = fs;
// fsp.js

const fs = require('fs');

const fsp = jest.createMockFromModule('fs/promises');

fsp.readFile = jest.fn(async (filePath) => fs.getMockFiles()[filePath]);
fsp.mkdir = jest.fn(async () => {});

module.exports = fsp;

And then in the suite:

// foo.unit.test.js

jest.mock('fs');
jest.mock('fs/promises');

fs.setMockFiles(...);

@SimenB
Copy link
Member

SimenB commented Mar 9, 2021

The whole example is probably a bit too verbose, but we can definitely add a comment above the existent example saying how it applies to /promise modules in node (other modules such as timers have the same thing)?

@thernstig
Copy link
Contributor Author

Yes, let this linger and maybe I can push a patch set when I get some time! Or if some other hero steps in before me.

@github-actions
Copy link

This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.

@github-actions github-actions bot added the Stale label Mar 12, 2022
@danielglazer
Copy link

Hey, @SimenB is the documentation for fs.promises mocks still needed? I did mocks just like it fairly recently if help still wanted on this

@github-actions github-actions bot removed the Stale label Apr 1, 2022
@github-actions
Copy link

github-actions bot commented Apr 1, 2023

This issue is stale because it has been open for 1 year with no activity. Remove stale label or comment or this will be closed in 30 days.

@github-actions github-actions bot added the Stale label Apr 1, 2023
@github-actions
Copy link

github-actions bot commented May 1, 2023

This issue was closed because it has been stalled for 30 days with no activity. Please open a new issue if the issue is still relevant, linking to this one.

@github-actions github-actions bot closed this as not planned Won't fix, can't repro, duplicate, stale May 1, 2023
@github-actions
Copy link

github-actions bot commented Jun 1, 2023

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.
Please note this issue tracker is not a help forum. We recommend using StackOverflow or our discord channel for questions.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jun 1, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants