Skip to content

Commit 1ff62d2

Browse files
authored
Merge pull request #30 from oslabs-beta/emma/TestingTestNewQueryPage
2 parents f12013d + 9aad997 commit 1ff62d2

File tree

5 files changed

+285
-5
lines changed

5 files changed

+285
-5
lines changed

.DS_Store

0 Bytes
Binary file not shown.

jest.config.ts

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ export default {
2323
// collectCoverageFrom: undefined,
2424

2525
// The directory where Jest should output its coverage files
26-
coverageDirectory: "coverage",
26+
coverageDirectory: 'coverage',
2727

2828
// An array of regexp pattern strings used to skip coverage collection
2929
// coveragePathIgnorePatterns: [
@@ -89,8 +89,9 @@ export default {
8989

9090
// A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
9191
moduleNameMapper: {
92-
"\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$": "<rootDir>/mocks/fileMock.js",
93-
"\\.(css|less)$": "<rootDir>/mocks/fileMock.js"
92+
'\\.(jpg|ico|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
93+
'<rootDir>/mocks/fileMock.js',
94+
'\\.(css|less)$': '<rootDir>/mocks/fileMock.js',
9495
},
9596

9697
// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
@@ -138,7 +139,8 @@ export default {
138139
// setupFiles: [],
139140

140141
// A list of paths to modules that run some code to configure or set up the testing framework before each test
141-
// setupFilesAfterEnv: [],
142+
//
143+
setupFilesAfterEnv: ['<rootDir>/src/setupTests.ts'],
142144

143145
// The number of seconds after which a test is considered as slow and reported as such in the results.
144146
// slowTestThreshold: 5,
@@ -147,7 +149,7 @@ export default {
147149
// snapshotSerializers: [],
148150

149151
// The test environment that will be used for testing
150-
testEnvironment: "jsdom",
152+
testEnvironment: 'jsdom',
151153

152154
// Options that will be passed to the testEnvironment
153155
// testEnvironmentOptions: {},

src/pages/TestNewQuery.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ const TestNewQuery: React.FC = () => {
228228
};
229229

230230
const saveQuery = async () => {
231+
console.log('Testing In Save Query ⭐️');
231232
try {
232233
// TODO remove commented out if not used selectedDb later
233234
// conditional to check that a query was run and that it had results
@@ -236,6 +237,7 @@ const TestNewQuery: React.FC = () => {
236237
alert('Please ensure you have ran a query and you received results');
237238
return;
238239
}
240+
console.log('Testing After If ⭐️');
239241

240242
// the BE returns back formatted query results
241243
// we want to extract just the data portion and send to the BE to save the query - since it's in str format, convert to obj

src/setupTests.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
//* This creates a jest setup file (this will run for every time a test file runs)
2+
import '@testing-library/jest-dom';
3+
import React from 'react';
4+
global.React = React;
Lines changed: 272 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,272 @@
1+
//* .spec (the expected behavior for the component) vs .test (straughtforward saying here are the tests)
2+
3+
import React from 'react';
4+
// render- lets us display the component
5+
// screen- allows us to query the DOM for els
6+
// waitFor- waits for async UI updates (ex- Axios completes)
7+
import { render, screen, waitFor } from '@testing-library/react';
8+
// simulates user behavior
9+
import userEvent from '@testing-library/user-event';
10+
import { BrowserRouter } from 'react-router-dom';
11+
import TestNewQuery from '../../src/pages/TestNewQuery';
12+
import axios, { Axios } from 'axios';
13+
import { AxiosResponse } from 'axios';
14+
15+
// Wrap component in BrowserRouter to render Register inside router (helper function)
16+
const renderWithRouter = (component: React.ReactElement): ReturnType<typeof render> => {
17+
return render(<BrowserRouter>{component}</BrowserRouter>);
18+
};
19+
20+
//? TESTS
21+
describe('Test New Query Component', () => {
22+
//? Testing (1): Test New Query heading renders
23+
it('renders the Test New Query heading', () => {
24+
renderWithRouter(<TestNewQuery />);
25+
// will check if the heading 'Test Your Query!' is rendering on the screen
26+
expect(screen.getByRole('heading', { name: /Test New Query/i })).toBeInTheDocument();
27+
});
28+
29+
//? Testing (2): input fields render
30+
it('renders the input fields (Query Name, DB Link, Query)', () => {
31+
renderWithRouter(<TestNewQuery />);
32+
// will check input fields are rendering on the screen
33+
expect(screen.getByPlaceholderText(/Name your query/i)).toBeInTheDocument();
34+
expect(screen.getByPlaceholderText(/Enter DB link here/i)).toBeInTheDocument();
35+
expect(screen.getByPlaceholderText(/Write your SQL query here/i)).toBeInTheDocument();
36+
});
37+
38+
//? Testing (3): buttons render
39+
it('render the buttons (Test Query, Save Query, Improve with AI)', () => {
40+
renderWithRouter(<TestNewQuery />);
41+
// will check buttons are rendering on the screen
42+
const testQueryButton = screen.getByRole('button', { name: /Run Query/i });
43+
const saveQueryButton = screen.getByRole('button', { name: /Save Query/i });
44+
const improveWithAIButton = screen.getByRole('button', { name: /Improve with AI/i });
45+
expect(testQueryButton).toBeInTheDocument();
46+
expect(saveQueryButton).toBeInTheDocument();
47+
expect(improveWithAIButton).toBeInTheDocument();
48+
});
49+
50+
//? Testing (4): input fields are editable
51+
it('checks input fields are editable', async (): Promise<void> => {
52+
renderWithRouter(<TestNewQuery />);
53+
// will find input fields by placeholder text
54+
const queryNameInput: HTMLTextAreaElement =
55+
screen.getByPlaceholderText(/Name your query/i);
56+
const dbLinkInput: HTMLTextAreaElement =
57+
screen.getByPlaceholderText(/Enter DB link here/i);
58+
const queryInput: HTMLTextAreaElement = screen.getByPlaceholderText(
59+
/Write your SQL query here/i
60+
);
61+
62+
// will simulate typing into the input field
63+
await userEvent.type(queryNameInput, 'My Test Query');
64+
await userEvent.type(dbLinkInput, 'My Test DB Link');
65+
await userEvent.type(queryInput, 'My Test SQL Query');
66+
67+
// will check if the input field has the expected value
68+
expect(queryNameInput).toHaveValue('My Test Query');
69+
expect(dbLinkInput).toHaveValue('My Test DB Link');
70+
expect(queryInput).toHaveValue('My Test SQL Query');
71+
});
72+
73+
//? Testing (5): clicking Run Query button triggers Get Req
74+
it('checks if clicking Run Query button triggers req to the BE', async () => {
75+
// mocking the axios Get Req
76+
const mockGet = jest.spyOn(axios, 'get').mockResolvedValue({
77+
data: ['Query: SELECT * FROM users', 'Date: 2025-04-11'],
78+
});
79+
renderWithRouter(<TestNewQuery />);
80+
// will simulate user typing into input fields
81+
const queryNameInput: HTMLTextAreaElement =
82+
screen.getByPlaceholderText(/Name your query/i);
83+
const dbLinkInput: HTMLTextAreaElement =
84+
screen.getByPlaceholderText(/Enter DB link here/i);
85+
const queryInput: HTMLTextAreaElement = screen.getByPlaceholderText(
86+
/Write your SQL query here/i
87+
);
88+
89+
await userEvent.type(queryNameInput, 'My Test Query');
90+
await userEvent.type(dbLinkInput, 'postgres://user:pass@host:5432/db');
91+
await userEvent.type(queryInput, 'SELECT * FROM users');
92+
93+
// Run Query button
94+
const runQueryButton = screen.getByRole('button', { name: /Run Query/i });
95+
96+
// will simulate user clicking the Run Query button
97+
await userEvent.click(runQueryButton);
98+
// wait / confirm for the mocked axios Get Req to be called
99+
await waitFor(() => {
100+
expect(mockGet).toHaveBeenCalledTimes(1);
101+
});
102+
// remove mock before next test
103+
mockGet.mockRestore();
104+
});
105+
106+
//? Testing (6): clicking Save Query button triggers Post Req
107+
it('checks if clicking Save Query button triggers req to the BE', async () => {
108+
// mocking running a query so we have queryResult
109+
const getMockResponse: AxiosResponse<{ metrics: string[]; otherMetrics: any[] }> = {
110+
data: {
111+
metrics: [
112+
'Query Name: Testing Sunday',
113+
'Query: SELECT * FROM people',
114+
'Date Run: 2025-04-11',
115+
'Execution Time: 0.042',
116+
],
117+
otherMetrics: [
118+
{
119+
planningTime: 1.932,
120+
actualTotalTime: 0.025,
121+
totalCost: 2.87,
122+
nodeType: 'Seq Scan',
123+
relationName: 'people',
124+
planRows: 87,
125+
actualRows: 87,
126+
sharedHit: 2,
127+
sharedRead: 0,
128+
},
129+
],
130+
},
131+
status: 200,
132+
statusText: 'OK',
133+
headers: {},
134+
config: {},
135+
};
136+
137+
const postMockResponse: AxiosResponse<any> = {
138+
data: 'Query saved successfully!',
139+
status: 200,
140+
statusText: 'OK',
141+
headers: {},
142+
config: {},
143+
};
144+
// mocking the axios Get Req w/ a mocked response
145+
const mockGet = jest.spyOn(axios, 'get').mockResolvedValue(getMockResponse);
146+
const mockPost = jest.spyOn(axios, 'post').mockResolvedValue(postMockResponse);
147+
148+
renderWithRouter(<TestNewQuery />);
149+
150+
// will simulate user typing into input fields
151+
const queryNameInput: HTMLTextAreaElement =
152+
screen.getByPlaceholderText(/Name your query/i);
153+
const dbLinkInput: HTMLTextAreaElement =
154+
screen.getByPlaceholderText(/Enter DB link here/i);
155+
const queryInput: HTMLTextAreaElement = screen.getByPlaceholderText(
156+
/Write your SQL query here/i
157+
);
158+
// will simulate user's inputed query data
159+
await userEvent.type(queryNameInput, 'My Test Query');
160+
await userEvent.type(dbLinkInput, 'postgres://user:pass@host:5432/db');
161+
await userEvent.type(queryInput, 'SELECT * FROM users');
162+
163+
// will simulate user clicking the Run Query button
164+
const runQueryButton = screen.getByRole('button', { name: /Run Query/i });
165+
await userEvent.click(runQueryButton);
166+
167+
// will wait for mocked axios Get Req to be called
168+
await waitFor(() => {
169+
expect(mockGet).toHaveBeenCalledTimes(1);
170+
});
171+
172+
// will simulate user clicking the Save Query button
173+
const saveQueryButton = screen.getByRole('button', { name: /Save Query/i });
174+
await userEvent.click(saveQueryButton);
175+
176+
// will wait for mocked axios Post Req to be called
177+
await waitFor(() => {
178+
expect(mockPost).toHaveBeenCalledTimes(1);
179+
});
180+
// remove mocks before next test
181+
mockPost.mockRestore();
182+
mockGet.mockRestore();
183+
});
184+
185+
//? Testing (7): clicking Run Query button renders a table w/ results
186+
it('checks if clicking Run Query button renders a table with results', async (): Promise<void> => {
187+
// mocking the axios Get Req w/ a mocked response
188+
// using TS to define the response
189+
const mockData = {
190+
metrics: [
191+
'Query Name: My Test Query',
192+
'Query: SELECT * FROM users',
193+
'Date Run: 2025-04-11',
194+
'Execution Time: 0.042',
195+
],
196+
otherMetrics: [
197+
{
198+
planningTime: 1.932,
199+
actualTotalTime: 0.025,
200+
totalCost: 2.87,
201+
nodeType: 'Seq Scan',
202+
relationName: 'people',
203+
planRows: 87,
204+
actualRows: 87,
205+
sharedHit: 2,
206+
sharedRead: 0,
207+
},
208+
],
209+
};
210+
// using TS to define the response
211+
const mockResponse: AxiosResponse<{ metrics: string[]; otherMetrics: any[] }> = {
212+
data: mockData,
213+
status: 200,
214+
statusText: 'OK',
215+
headers: {},
216+
config: {},
217+
};
218+
// mocking the axios Get Req w/ a mocked response
219+
const mockGet = jest.spyOn(axios, 'get').mockResolvedValue(mockResponse);
220+
221+
renderWithRouter(<TestNewQuery />);
222+
223+
// input fields
224+
const queryNameInput: HTMLTextAreaElement =
225+
screen.getByPlaceholderText(/Name your query/i);
226+
const dbLinkInput: HTMLTextAreaElement =
227+
screen.getByPlaceholderText(/Enter DB link here/i);
228+
const queryInput: HTMLTextAreaElement = screen.getByPlaceholderText(
229+
/Write your SQL query here/i
230+
);
231+
232+
// will simulate user typing into input fields
233+
await userEvent.type(queryNameInput, 'My Test Query');
234+
await userEvent.type(dbLinkInput, 'postgres://user:pass@host:5432/db');
235+
await userEvent.type(queryInput, 'SELECT * FROM users');
236+
237+
// simulate user clicking Run Query button
238+
const runQueryButton: HTMLButtonElement = screen.getByRole('button', {
239+
name: /Run Query/i,
240+
});
241+
242+
await userEvent.click(runQueryButton);
243+
screen.debug();
244+
245+
// will wait for QUery Results heading to render
246+
await waitFor(() => {
247+
expect(screen.getByText(/Query Results/i)).toBeInTheDocument();
248+
});
249+
250+
// will check that all parts of our mocked results render
251+
expect(screen.getByText(/My Test Query/i)).toBeInTheDocument();
252+
expect(screen.getByText(/SELECT \* FROM users/i)).toBeInTheDocument();
253+
expect(screen.getByText(/2025-04-11/i)).toBeInTheDocument();
254+
expect(screen.getByText(/0.042/i)).toBeInTheDocument();
255+
256+
// remove mock before next test
257+
mockGet.mockRestore();
258+
});
259+
260+
//? Testing (8): clicking Run Query button renders error message
261+
// mock the axios Get Req to fail
262+
// confirm error message renders (error running query, check db link and query)
263+
264+
//? Testing (9): clicking Run Query button clears the input fields
265+
// mock running a query
266+
// confirm input fields are cleared
267+
268+
//? Testing (9): clicking Save Query button renders 'Query Saved!'
269+
// mock saving a query
270+
// confirm 'Query Saved!' renders
271+
// currently THIS is failing. Even if the req to save the query fails, the 'Query Saved!' message still renders
272+
});

0 commit comments

Comments
 (0)