-
Notifications
You must be signed in to change notification settings - Fork 281
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: implement mocking in feature tests #9715
Conversation
The latest updates on your projects. Learn more about Vercel for Git ↗︎
|
A production App ID was automatically generated for this PR. (log)
Click here to copy & paste above information.
|
🚨 Lighthouse report for the changes in this PR:
Lighthouse ran with https://deriv-app-git-fork-markwylde-deriv-integration-with-mocks.binary.sx/ |
@markwylde-deriv nice job. i have some questions and concerns here:
|
@markwylde-deriv In the above example, We only set the mocks when starting the test, How to change the mock in the flow? 🤔
|
Great point. I haven't catered for this. Would something like this work? test('it shows the current name', async ({ page, baseURL }) => {
const mocks = await setupMocks({
baseURL,
page,
mocks: [mockGeneral, mockLoggedIn, mockResidentsList, mockStatesList],
});
await page.goto(`${baseURL}/account/personal-details`);
const firstName = await page.getByLabel('First name*').first();
expect(await firstName.inputValue()).toBe('Jane');
const lastName = await page.getByLabel('Last name*').first();
expect(await lastName.inputValue()).toBe('Smith');
mocks.add(mockSecondThing);
const dateOfBirth = await page.getByLabel('Date of birth*').first();
expect(await dateOfBirth.inputValue()).toBe('01-01-1980');
mocks.remove(mockSecondThing);
const citizenship = await page.getByLabel('Citizenship').first();
expect(await citizenship.inputValue()).toBe('Thailand');
}); |
I think there's a couple of ways to do this. ExtendingWe can do this as it follows a sort of middleware/chain flow. So just a mock after the first one, then change the response how you want. function add_req_id ({ request, response, req_id }) {
response = {
req_id
}
}
function add_hello ({ request, response, req_id }) {
response = {
hello: 'world'
}
}
await setupMocks({
baseURL,
page,
mocks: [add_req_id, add_hello],
}); OverrideA mock could also be given arguments. For example: const mock_time = (override) => (context) {
if (context.request.time === 1) {
context.response = {
echo_req: context.request,
req_id: context.req_id,
msg_type: 'time',
time: (Date.now() / 1000).toFixed(0),
...override
};
}
}
await setupMocks({
baseURL,
page,
mocks: [mock_time({ hello: 'world' })],
});
I'd say use mocks. For anything that needs an actual server, I think the end-to-end/qa team should focus on that. So yeah, we would mock the demo account. However, you could just extend from mock (as proposed above?)
Does the first point answer this? |
I think we should be able to override the default mocks, instead of replacing the whole thing 🤔 The API could look something like this maybe; // Set up test stuff
const server = createServer(...);
// Perform an action and return mocked response
server.send(...).ressponse(...);
// Do assertion
expect(stuff).toBe(goodStuff); |
Yeah @farzin-deriv. I think you're right. Would my response to Ako solve this? |
If I remember correctly @mohsen-deriv did some good stuff before for mocking the server and providing the tooling for the test, Why abandon that POC? 😅 |
Yeah, Michio's stuff looked cool, specifically around the types/typescript of the websocket endpoint. Could come in really handy. I'll speak to him about how we can implement that in here. |
In bdb5045, |
Kudos, SonarCloud Quality Gate passed!
|
@markwylde-deriv Thanks for your complete documentation 🙏 🔥 |
import { Context } from '../../utils/mocks/mocks'; | ||
|
||
export default function mock_landing_company(context: Context) { | ||
if ('landing_company' in context.request && context.request.landing_company === 'th') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
deposit_commission: '0', | ||
email: 'teclasarojani@gmail.com', | ||
further_information: | ||
'ආයුබෝවන් ඔබට අවශ්ය Binary / Deriv $ මිලට ගැනීමට අප සමග සමිබන්ධ වෙන්න. Bank Transfer( cash ), USDT Exchange , E-wallet Exchange සමග ඉතා කඩිනම් සුහදශීලී හා ලාබදායි ලෙස ඔබට අපගෙන් ලබාගත හැක. Binary/ Deriv Dollars,USDT, Crypto மாற்றம் அல்லது வாங்குதல் மற்றும் விற்பனை நோக்கங்களுக்காக என்னை தொடர்பு கொள்ளவும். குறைந்த விகிதங்கள் மற்றும் வேகமான சேவைகள் எங்களிடம் பெற்றுக்கொள்ளலாம். You are warmly welcome to my premium payment agent group. Whatsapp following Number for more details.', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What language is this ? 😅
if ( | ||
'platform' in context.request && | ||
context.request.platform === 'dxtrade' && | ||
context.request.trading_servers === 1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { Context } from '../../utils/mocks/mocks'; | ||
|
||
export default function mock_platform_mt5(context: Context) { | ||
if ('platform' in context.request && context.request.platform === 'mt5' && context.request.trading_servers === 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if ( | ||
'trading_platform_accounts' in context.request && | ||
context.request.trading_platform_accounts === 1 && | ||
context.request.platform === 'derivez' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import mock_time from './time'; | ||
import mock_website_status from './website_status'; | ||
|
||
const general = context => { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
const general = context => { | |
const general = (context: Context) => { |
Can we define type for this? 🤔
import { Context } from '../../utils/mocks/mocks'; | ||
|
||
function mock_residents_list(context: Context) { | ||
if (context.request.residence_list === 1) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
import { Context } from '../../utils/mocks/mocks'; | ||
|
||
function mock_states_list(context: Context) { | ||
if (context.request.states_list === 'th') { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
|
||
wss.on('connection', ws => { | ||
ws.on('message', async message => { | ||
const parsedMessage = JSON.parse(message); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -0,0 +1,70 @@ | |||
import { Context } from '../../utils/mocks/mocks'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we use absolute import instead of this pattern? 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Too Large
This pull request is too large, and reviewing it will be difficult. In addition, because of ChatGPT API limitations, this PR cannot be sent for external review. Please consider breaking this PR into smaller ones
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull Request Too Large
This pull request is too large, and reviewing it will be difficult. In addition, because of ChatGPT API limitations, this PR cannot be sent for external review. Please consider breaking this PR into smaller ones
POC moved to #9761 |
Refactor current end-to-end tests to work with mocks.
Local Mock
exampleMock.ts
file, that can be run withts-node ./exampleMock.ts
to start a web socket server on `localhost:10443'Using mocks in tests
Each test should setup the mocks they need from the pool of mocks provided.
Writing your own mocks
A mock is simply a function that is given a context object that contains the following keys:
Extending Mocks
If you want to change how a base mock works, or "extend" a mock, you can use the middleware like approach.
For example, let's say you want to add a
day
to thetime
endpoint. You can use themockTime
base mock, but add another mock to add theday
key.| Note: The response will, by default, be undefined. Above,
mockTime
creates the first response, thenmockTimeMonday
get's the mutated response and adds a new key. For that reason, the order of mocks is important.Dynamically changing
If you have a test that needs to change a mock, in the middle of the run, you can use the
add
andremove
functions returned fromcreateMockServer