Skip to content

Commit

Permalink
Merge pull request #9 from jreyesr/testing
Browse files Browse the repository at this point in the history
More tests
  • Loading branch information
jreyesr authored Jan 20, 2024
2 parents 514b483 + abd101f commit e0f3d7f
Show file tree
Hide file tree
Showing 12 changed files with 247 additions and 55 deletions.
9 changes: 9 additions & 0 deletions .parcelrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"extends": "@parcel/config-default",
"transformers": {
"*.{js,mjs,jsx,cjs,ts,tsx}": [
"@parcel/transformer-js",
"@parcel/transformer-react-refresh-wrap"
]
}
}
25 changes: 13 additions & 12 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ The plugin adds a template tag to mark the places that you want to replace. To a

When configuring the tag, set the following two values:

* The name of the CSV column that will be replaced in this tag's location. Copy it from the first line of the CSV file, exactly (including capitalization)
* A sample value. This value will be used when sending the request manually. This is the value that you would have to edit manually if this plugin did not exist.
- The name of the CSV column that will be replaced in this tag's location. Copy it from the first line of the CSV file, exactly (including capitalization)
- A sample value. This value will be used when sending the request manually. This is the value that you would have to edit manually if this plugin did not exist.

The live preview will always show the value of the `Sample value` field. The value will only vary when sending the request via the Batch Request dropdown option (see below).

Expand Down Expand Up @@ -63,19 +63,20 @@ Since `v1.2.0`, there is a Global Configuration dialog in which you can select a
1. Identify your Insomnia plugin folder. On Ubuntu, it should be `~/.config/Insomnia/plugins`. Alternatively, open Insomnia, select the `Application>Preferences` menu, go to the Plugins tab, then click the `Reveal Plugins Folder` button.
2. On that folder, run `git clone https://github.com/jreyesr/insomnia-plugin-batch-requests`.
3. Run `npm i`.
3. Run `npm run dev`. This will start a dev server that will generate the `dist/main.js` file and keep it updated whenever you change the source files.
4. Open the Insomnia Plugins dialog (see the first step). It should display the plugin, since it's in the correct folder. It's not necessary to manually install it.
5. Create and checkout a new branch.
6. Hackity hack on the source files.
7. Whenever you save a file, the `dist/main.js` file will be updated. To make Insomnia pick up the changes, select the `Tools>Reload plugins` option from the top menus. Alternatively, press `Alt+T`, then release both, then press `R`.
8. Make commit.
9. GOTO 6
10. Update the package version in `package.json`.
11. When done, submit a PR and merge it. The CD should pick it up, compile a package and upload it to NPM.
4. Run `npm run dev`. This will start a dev server that will generate the `dist/main.js` file and keep it updated whenever you change the source files.
5. Open the Insomnia Plugins dialog (see the first step). It should display the plugin, since it's in the correct folder. It's not necessary to manually install it.
6. Create and checkout a new branch.
7. Hackity hack on the source files.
8. Whenever you save a file, the `dist/main.js` file will be updated. To make Insomnia pick up the changes, select the `Tools>Reload plugins` option from the top menus. Alternatively, press `Alt+T`, then release both, then press `R`.
9. To run tests, run `npm run test`
10. Make commit.
11. GOTO 6
12. Update the package version in `package.json`.
13. When done, submit a PR and merge it. The CD should pick it up, compile a package and upload it to NPM.

## Releasing

1. Ensure that the package version in `package.json` has been bumped.
2. Make all required commits, ensure that `master` has the code.
3. Create a Github Release, tag it like the version in `package.json`.
4. The CD runner should create the release and publish it.
4. The CD runner should create the release and publish it.
9 changes: 6 additions & 3 deletions __tests__/ActionButton.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {render, fireEvent, waitFor} from '@testing-library/react';
import {render} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import ActionButton from '../components/ActionButton'

Expand All @@ -15,22 +16,24 @@ it('renders with default values', () => {

it("calls the callback when clicked", async () => {
const cb = jest.fn();
const user = userEvent.setup();
const {container} = render(
<ActionButton onClick={cb} />,
);

fireEvent.click(container.firstChild);
await user.click(container.firstChild);

expect(cb).toBeCalled();
});

it("does not call the callback when disabled", async () => {
const cb = jest.fn();
const user = userEvent.setup();
const {container} = render(
<ActionButton onClick={cb} disabled={true}/>,
);

fireEvent.click(container.firstChild);
await user.click(container.firstChild);

expect(cb).not.toBeCalled();
});
147 changes: 141 additions & 6 deletions __tests__/BatchDialog.test.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,44 @@
import {render, fireEvent, waitFor} from '@testing-library/react';
import {render, within, waitFor} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import * as utils from '../utils';
import BatchDialog from '../components/BatchDialog'


const mockAlert = jest.fn((title, text) => {});
const mockGetItem = jest.fn(k => JSON.stringify({defaultDelay: 0}));
const mockAlert = jest.fn();
const mockGetItem = jest.fn();
const mockSetItem = jest.fn();
const mockRemoveItem = jest.fn();
const mockSendRequest = jest.fn();

const originalReadCsv = utils.readCsv;
const originalSelectFile = utils.selectFile;
utils.readCsv = jest.fn();
utils.selectFile = jest.fn();

beforeEach(() => {
mockGetItem.mockReturnValue(JSON.stringify({defaultDelay: 0.1}));
utils.readCsv.mockImplementation(originalReadCsv);
utils.selectFile.mockImplementation(originalSelectFile);
})

afterEach(() => {
mockAlert.mockClear();
mockGetItem.mockClear();
jest.clearAllMocks();
})

const mockContext = {
store: {
hasItem: jest.fn(k => true),
getItem: mockGetItem,
setItem: mockSetItem,
removeItem: mockRemoveItem,
},
app: {
alert: mockAlert,
},
network: {
sendRequest: mockSendRequest,
}
};

it('renders with default delay', async () => {
Expand All @@ -28,8 +48,123 @@ it('renders with default delay', async () => {

const delayField = queryByLabelText(/delay/i);
// wait for onMount effects to run
await waitFor(() => expect(delayField).toHaveValue(0));
await waitFor(() => expect(delayField).toHaveValue(0.1));

expect(getByText(/run!/i)).toBeDefined();
});

it('does not enable the buttons on load', async () => {
const {queryByLabelText, getByText} = render(
<BatchDialog context={mockContext}/>,
);

const delayField = queryByLabelText(/delay/i);
// wait for onMount effects to run
await waitFor(() => expect(delayField).toHaveValue(0.1));

expect(getByText(/run!/i)).toBeDisabled();
expect(getByText(/save/i)).toBeDisabled();
});

it('prompts the user to choose a file', async () => {
const {queryByLabelText, getByText} = render(
<BatchDialog context={mockContext}/>,
);

const delayField = queryByLabelText(/delay/i);
// wait for onMount effects to run
await waitFor(() => expect(delayField).toHaveValue(0.1));

expect(getByText(/choose a file above to preview it!/i)).toBeDefined();
});

it('reads a CSV file when clicking Load button', async () => {
utils.selectFile.mockReturnValue({canceled: false, filePath: "test.csv.file"});
utils.readCsv.mockReturnValue({
headers: ["a", "b"],
results: [{a: "a1", b: "b1", c: "c1"}]
});
const user = userEvent.setup();
const {queryByLabelText, getByText, getByTestId} = render(
<BatchDialog context={mockContext}/>,
);

const delayField = queryByLabelText(/delay/i);
// wait for onMount effects to run
await waitFor(() => expect(delayField).toHaveValue(0.1));
await user.click(getByText("Choose File"));

expect(utils.readCsv).toBeCalledWith("test.csv.file");
expect(within(getByTestId("sampletable")).queryAllByText("a1")).toHaveLength(1);
expect(within(getByTestId("sampletable")).queryAllByText("b1")).toHaveLength(1);
expect(within(getByTestId("sampletable")).queryAllByText("c1")).toHaveLength(0);
});

it('does not read file when file selection canceled', async () => {
utils.selectFile.mockReturnValue({canceled: true, filePath: "test.csv.file"});
const user = userEvent.setup();
const {queryByLabelText, getByText, getByTestId} = render(
<BatchDialog context={mockContext}/>,
);

const delayField = queryByLabelText(/delay/i);
// wait for onMount effects to run
await waitFor(() => expect(delayField).toHaveValue(0.1));
await user.click(getByText("Choose File"));

expect(utils.readCsv).not.toBeCalled();
});

const prepareForSending = () => {
utils.selectFile.mockReturnValue({canceled: false, filePath: "test.csv.file"});
utils.readCsv.mockReturnValue({
headers: ["a", "b"],
results: [{a: "a1", b: "b1", c: "c1"}, {a: "a2", b: "b2", c: "c2"}]
});
mockGetItem.mockReturnValue(JSON.stringify({defaultDelay: 0}));
}

it('sets and deletes storage across requests', async () => {
const user = userEvent.setup();
prepareForSending();
const {getByText} = render(
<BatchDialog context={mockContext} request={{_id: "test-req-id"}}/>,
);

await user.click(getByText("Choose File"));
await user.click(getByText("Run!"));

expect(mockSetItem).toBeCalledTimes(2); // once for every line in the CSV
expect(mockSetItem).toHaveBeenNthCalledWith(1,
"test-req-id.batchExtraData",
'{"a":"a1","b":"b1","c":"c1"}')
expect(mockRemoveItem).toHaveBeenLastCalledWith("test-req-id.batchExtraData");
});

it('actually makes network requests', async () => {
const user = userEvent.setup();
prepareForSending();
const {getByText} = render(
<BatchDialog context={mockContext} request={{_id: "test-req-id"}}/>,
);

await user.click(getByText("Choose File"));
await user.click(getByText("Run!"));

expect(mockSendRequest).toBeCalledTimes(2); // once for every line in the CSV
expect(mockSendRequest).toHaveBeenLastCalledWith({_id: "test-req-id"})
});

it('processes response data', async () => {
const user = userEvent.setup();
prepareForSending();
const {getByText} = render(
<BatchDialog context={mockContext} request={{_id: "test-req-id"}}/>,
);

await user.click(getByText("Choose File"));
await user.click(getByText("Run!"));

expect(mockSendRequest).toBeCalledTimes(2); // once for every line in the CSV
expect(mockSendRequest).toHaveBeenLastCalledWith({_id: "test-req-id"})
});
24 changes: 15 additions & 9 deletions __tests__/BatchDialogSettings.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {render, fireEvent, waitFor} from '@testing-library/react';
import {render, waitFor} from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import BatchDialogSettings from '../components/BatchDialogSettings'

Expand Down Expand Up @@ -40,26 +41,29 @@ it('triggers the save function', async () => {
setItem: mockSetItem,
},
}
const user = userEvent.setup();
const {getByText, getByLabelText} = render(
<BatchDialogSettings context={mockContextWithSet} />,
);

fireEvent.change(getByLabelText(/default delay/i), {target: {value: 0.3}})
fireEvent.click(getByText("Save"));
await user.type(getByLabelText(/default delay/i), "0.3")
await user.click(getByText("Save"));
await waitFor(() => expect(mockSetItem).toBeCalled())
});

it('rejects negative numbers', async () => {
const {queryByLabelText, getByText, getByLabelText} = render(
const user = userEvent.setup();
const {queryByLabelText} = render(
<BatchDialogSettings context={mockContext} />,
);

const delayField = queryByLabelText(/default delay/i);
// wait for onMount effects to run
await waitFor(() => expect(delayField).toHaveValue(0.2));

fireEvent.change(delayField, {target: {value: -.1}})
expect(delayField).toHaveValue(0.2);
await user.clear(delayField);
await user.type(delayField, "-0.1")
expect(delayField).toHaveValue(0.1);
});

it("doesn't enable the Save button when loading", async () => {
Expand All @@ -73,13 +77,14 @@ it("doesn't enable the Save button when loading", async () => {
});

it("enables the Save button after a change is made", async () => {
const user = userEvent.setup();
const {getByText, getByLabelText} = render(
<BatchDialogSettings context={mockContext} />,
);
// wait for onMount effects to run
await waitFor(() => expect(getByLabelText(/default delay/i)).toHaveValue(0.2));

fireEvent.change(getByLabelText(/default delay/i), {target: {value: 0.3}})
await user.type(getByLabelText(/default delay/i), "0.3")
expect(getByText("Save")).toBeEnabled();
});

Expand All @@ -92,11 +97,12 @@ it("redisables the Save button after saving changes", async () => {
setItem: mockSetItem,
},
}
const user = userEvent.setup();
const {getByText, getByLabelText} = render(
<BatchDialogSettings context={mockContextWithSet} />,
);
fireEvent.change(getByLabelText(/default delay/i), {target: {value: 0.3}})
fireEvent.click(getByText("Save"));
await user.type(getByLabelText(/default delay/i), "0.3")
await user.click(getByText("Save"));

// wait for effects to settle
await waitFor(() => expect(getByText("Save")).toBeDisabled());
Expand Down
6 changes: 4 additions & 2 deletions __tests__/CheckBox.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import {render, fireEvent} from '@testing-library/react';
import { render } from '@testing-library/react';
import userEvent from '@testing-library/user-event';

import CheckBox from '../components/CheckBox'

Expand All @@ -24,11 +25,12 @@ it('renders when unchecked', () => {

it("calls the callback when clicked", async () => {
const cb = jest.fn();
const user = userEvent.setup();
const {container} = render(
<CheckBox state={false} onToggle={cb} />,
);

fireEvent.click(container.firstChild);
await user.click(container.firstChild);

expect(cb).toBeCalled();
expect(cb).toBeCalledWith(true);
Expand Down
Loading

0 comments on commit e0f3d7f

Please sign in to comment.