commit
46c110b70c
@ -0,0 +1,68 @@ |
||||
#!/usr/bin/env bash |
||||
|
||||
set -e |
||||
set -u |
||||
set -o pipefail |
||||
|
||||
if [[ "${CI:-}" != 'true' ]] |
||||
then |
||||
printf '%s\n' 'CI environment variable must be set to true' |
||||
exit 1 |
||||
fi |
||||
|
||||
if [[ "${CIRCLECI:-}" != 'true' ]] |
||||
then |
||||
printf '%s\n' 'CIRCLECI environment variable must be set to true' |
||||
exit 1 |
||||
fi |
||||
|
||||
if [[ "${CIRCLE_BRANCH}" != "develop" ]] |
||||
then |
||||
printf 'This is not develop branch' |
||||
exit 0 |
||||
fi |
||||
|
||||
if [[ -z "${GITHUB_TOKEN:-}" ]] |
||||
then |
||||
printf '%s\n' 'GITHUB_TOKEN environment variable must be set' |
||||
exit 1 |
||||
elif [[ -z "${GITHUB_TOKEN_USER:-}" ]] |
||||
then |
||||
printf '%s\n' 'GITHUB_TOKEN_USER environment variable must be set' |
||||
exit 1 |
||||
fi |
||||
|
||||
mkdir temp |
||||
|
||||
git config --global user.email "metamaskbot@users.noreply.github.com" |
||||
|
||||
git config --global user.name "MetaMask Bot" |
||||
|
||||
git clone git@github.com:MetaMask/extension_bundlesize_stats.git temp |
||||
|
||||
if [[ -f "temp/stats/bundle_size_stats-${CIRCLE_SHA1}.json" ]] |
||||
then |
||||
printf 'Bundle size of the commit is already recorded' |
||||
cd .. |
||||
rm -rf temp |
||||
exit 0 |
||||
fi |
||||
|
||||
cp -R test-artifacts/chrome/mv3/bundle_size_stats.json temp/stats |
||||
|
||||
echo " bundle_size_stats-${CIRCLE_SHA1}.json" >> temp/stats/fileList.txt |
||||
|
||||
mv temp/stats/bundle_size_stats.json "temp/stats/bundle_size_stats-${CIRCLE_SHA1}.json" |
||||
|
||||
cd temp |
||||
|
||||
git add . |
||||
|
||||
git commit --message "Bundle size at commit: ${CIRCLE_SHA1}" |
||||
|
||||
repo_slug="$CIRCLE_PROJECT_USERNAME/extension_bundlesize_stats" |
||||
git push "https://$GITHUB_TOKEN_USER:$GITHUB_TOKEN@github.com/$repo_slug" main |
||||
|
||||
cd .. |
||||
|
||||
rm -rf temp |
@ -0,0 +1,307 @@ |
||||
import { Meta, Canvas, Story } from '@storybook/addon-docs'; |
||||
|
||||
<Meta title="Foundations / Shadow" /> |
||||
|
||||
# Shadow |
||||
|
||||
Shadows convey elevation of elements on a surface |
||||
|
||||
## Size |
||||
|
||||
There are 4 different sizes of shadow in MetaMask |
||||
|
||||
<div |
||||
style={{ |
||||
display: 'grid', |
||||
gap: '32px', |
||||
gridTemplateColumns: 'repeat(auto-fill, 200px)', |
||||
marginTop: 16, |
||||
marginBottom: 16, |
||||
}} |
||||
> |
||||
<div |
||||
style={{ |
||||
height: 100, |
||||
backgroundColor: 'var(--color-background-default)', |
||||
boxShadow: 'var(--shadow-size-xs) var(--color-shadow-default', |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
}} |
||||
> |
||||
XS |
||||
</div> |
||||
<div |
||||
style={{ |
||||
height: 100, |
||||
backgroundColor: 'var(--color-background-default)', |
||||
boxShadow: 'var(--shadow-size-sm) var(--color-shadow-default', |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
}} |
||||
> |
||||
SM |
||||
</div> |
||||
<div |
||||
style={{ |
||||
height: 100, |
||||
backgroundColor: 'var(--color-background-default)', |
||||
boxShadow: 'var(--shadow-size-md) var(--color-shadow-default', |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
}} |
||||
> |
||||
MD |
||||
</div> |
||||
<div |
||||
style={{ |
||||
height: 100, |
||||
backgroundColor: 'var(--color-background-default)', |
||||
boxShadow: 'var(--shadow-size-lg) var(--color-shadow-default', |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
}} |
||||
> |
||||
LG |
||||
</div> |
||||
</div> |
||||
|
||||
| Size | CSS | |
||||
| ------ | ----------------------- | |
||||
| **XS** | `var(--shadow-size-xs)` | |
||||
| **SM** | `var(--shadow-size-sm)` | |
||||
| **MD** | `var(--shadow-size-md)` | |
||||
| **LG** | `var(--shadow-size-lg)` | |
||||
|
||||
## Color |
||||
|
||||
As well as the neutral colors for shadow 2 other colors exist that are used for the primary and error/danger button hover states |
||||
|
||||
<div |
||||
style={{ |
||||
display: 'grid', |
||||
gap: '32px', |
||||
gridTemplateColumns: 'repeat(auto-fill, 200px)', |
||||
marginTop: 16, |
||||
marginBottom: 16, |
||||
}} |
||||
> |
||||
<div |
||||
style={{ |
||||
height: 100, |
||||
backgroundColor: 'var(--color-background-default)', |
||||
boxShadow: 'var(--shadow-size-lg) var(--color-shadow-default', |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
}} |
||||
color="default" |
||||
> |
||||
<span>Default</span> |
||||
</div> |
||||
<div |
||||
style={{ |
||||
height: 100, |
||||
backgroundColor: 'var(--color-primary-default)', |
||||
boxShadow: 'var(--shadow-size-lg) var(--color-primary-shadow', |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
color: 'var(--color-primary-inverse)', |
||||
}} |
||||
> |
||||
<span>Primary</span> |
||||
</div> |
||||
<div |
||||
style={{ |
||||
height: 100, |
||||
backgroundColor: 'var(--color-error-default)', |
||||
boxShadow: 'var(--shadow-size-lg) var(--color-error-shadow', |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
color: 'var(--color-error-inverse)', |
||||
}} |
||||
> |
||||
<span>Error/Danger</span> |
||||
</div> |
||||
</div> |
||||
|
||||
| Color | CSS | |
||||
| ----------- | ----------------------------- | |
||||
| **neutral** | `var(--color-shadow-default)` | |
||||
| **primary** | `var(--color-primary-shadow)` | |
||||
| **danger** | `var(--color-error-shadow)` | |
||||
|
||||
## Example usage |
||||
|
||||
Using both size and color tokens, different shadows can be applied to components |
||||
|
||||
<div> |
||||
<div |
||||
style={{ |
||||
display: 'grid', |
||||
gap: '32px', |
||||
gridTemplateColumns: 'repeat(auto-fill, 200px)', |
||||
marginBottom: '64px', |
||||
}} |
||||
> |
||||
<div |
||||
style={{ |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
height: 100, |
||||
textAlign: 'center', |
||||
boxShadow: 'var(--shadow-size-xs) var(--color-shadow-default)', |
||||
}} |
||||
> |
||||
<span>Card</span> |
||||
</div> |
||||
<div |
||||
style={{ |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
height: 100, |
||||
textAlign: 'center', |
||||
boxShadow: 'var(--shadow-size-sm) var(--color-shadow-default)', |
||||
}} |
||||
> |
||||
<span>Dropdown</span> |
||||
</div> |
||||
<div |
||||
style={{ |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
height: 100, |
||||
textAlign: 'center', |
||||
boxShadow: 'var(--shadow-size-md) var(--color-shadow-default)', |
||||
}} |
||||
> |
||||
<span>Toast</span> |
||||
</div> |
||||
<div |
||||
style={{ |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
height: 100, |
||||
textAlign: 'center', |
||||
boxShadow: 'var(--shadow-size-lg) var(--color-shadow-default)', |
||||
}} |
||||
> |
||||
<span>Modal</span> |
||||
</div> |
||||
</div> |
||||
<div |
||||
style={{ |
||||
display: 'grid', |
||||
gap: '32px', |
||||
gridTemplateColumns: 'repeat(auto-fill, 200px)', |
||||
}} |
||||
> |
||||
<div |
||||
style={{ |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
height: 100, |
||||
textAlign: 'center', |
||||
boxShadow: 'var(--component-button-primary-shadow)', |
||||
backgroundColor: 'var(--color-primary-default)', |
||||
color: 'var(--color-primary-inverse)', |
||||
}} |
||||
> |
||||
<span>Button Primary Hover</span> |
||||
</div> |
||||
<div |
||||
style={{ |
||||
borderRadius: '4px', |
||||
display: 'grid', |
||||
alignContent: 'center', |
||||
justifyContent: 'center', |
||||
spanAlign: 'center', |
||||
height: 100, |
||||
textAlign: 'center', |
||||
boxShadow: 'var(--component-button-danger-shadow)', |
||||
backgroundColor: 'var(--color-error-default)', |
||||
color: 'var(--color-error-inverse)', |
||||
}} |
||||
> |
||||
<span>Button Error/Danger Hover</span> |
||||
</div> |
||||
</div> |
||||
</div> |
||||
|
||||
| Component | JS | CSS | |
||||
| ------------------------ | ---------------------------------------------------------------- | --- | |
||||
| **Card** | `box-shadow: var(--shadow-size-xs) var(--color-shadow-default);` | |
||||
| **Dropdown** | `box-shadow: var(--shadow-size-sm) var(--color-shadow-default);` | |
||||
| **Toast** | `box-shadow: var(--shadow-size-md) var(--color-shadow-default);` | |
||||
| **Modal** | `box-shadow: var(--shadow-size-lg) var(--color-shadow-default);` | |
||||
| **Button Primary Hover** | `box-shadow: var(--shadow-size-sm) var(--color-primary-shadow);` | |
||||
| **Button Danger Hover** | `box-shadow: var(--shadow-size-sm) var(--color-error-shadow);` | |
||||
|
||||
## Takeaways |
||||
|
||||
- Try to avoid using static media queries in your code |
||||
- Try to use the provided SCSS mixins |
||||
|
||||
### ❌ Don't do this |
||||
|
||||
Don't use static media queries in your code |
||||
|
||||
```css |
||||
/** |
||||
* Don't do this |
||||
* Static box-shadows create inconsistency in elevation of elements |
||||
**/ |
||||
.card { |
||||
box-shadow: 0 0 5px 0 rgba(0, 0, 0, 0.2); |
||||
} |
||||
``` |
||||
|
||||
### ✅ Do this |
||||
|
||||
Do use the provided shadow design token css variables |
||||
|
||||
```css |
||||
.card { |
||||
box-shadow: var(--shadow-size-xs) var(--color-shadow-default); |
||||
} |
||||
``` |
||||
|
||||
## References |
||||
|
||||
- [Shadow design tokens](https://metamask.github.io/design-tokens/?path=/docs/shadows-shadows--shadow) |
||||
- [Figma light theme colors library(shadows page)](https://www.figma.com/file/kdFzEC7xzSNw7cXteqgzDW/%5BColor%5D-Light-Theme?node-id=753%3A719)(internal use only) |
||||
- [Figma dark theme colors library(shadows page)](https://www.figma.com/file/rLKsoqpjyoKauYnFDcBIbO/%5BColor%5D-Dark-Theme?node-id=522%3A1022)(internal use only) |
@ -0,0 +1,125 @@ |
||||
import { Meta } from '@storybook/addon-docs'; |
||||
|
||||
<Meta title="Foundations / Breakpoints" /> |
||||
|
||||
# Breakpoints |
||||
|
||||
Breakpoints are used for responsive layout |
||||
|
||||
## Screen Sizes |
||||
|
||||
There are 4 screen sizes that make up the breakpoints for the MetaMask extension |
||||
|
||||
- base: `0px` |
||||
- sm: `576px` |
||||
- md: `768px` |
||||
- lg: `1280px` |
||||
|
||||
### SCSS |
||||
|
||||
There are Sass variables and mixins available for use for both min and max screens sizes |
||||
|
||||
### Variables |
||||
|
||||
```css |
||||
$screen-sm-max /* 575px */ |
||||
$screen-md-max /* 767px */ |
||||
$screen-lg-max /* 1279px */ |
||||
|
||||
$screen-sm-min /* 576px */ |
||||
$screen-md-min /* 768px */ |
||||
$screen-lg-min /* 1280px */ |
||||
``` |
||||
|
||||
### Mixins |
||||
|
||||
```css |
||||
/* Max screen size */ |
||||
@include screen-sm-max { |
||||
/* equivalent css @media screen and (max-width: 575px) */ |
||||
} |
||||
@include screen-md-max { |
||||
/* equivalent css @media screen and (max-width: 767px) */ |
||||
} |
||||
@include screen-lg-max { |
||||
/* equivalent css @media screen and (max-width: 1279px) */ |
||||
} |
||||
|
||||
/* Min screen size */ |
||||
@include screen-sm-min { |
||||
/* equivalent css @media screen and (min-width: 576px) */ |
||||
} |
||||
@include screen-md-min { |
||||
/* equivalent css @media screen and (min-width: 768px) */ |
||||
} |
||||
@include screen-lg-min { |
||||
/* equivalent css @media screen and (min-width: 1280px) */ |
||||
} |
||||
``` |
||||
|
||||
Migrating from the old sass variables to the new mixins looks like this |
||||
|
||||
```css |
||||
/* Max width */ |
||||
/* Instead of the media query and sass variable */ |
||||
@media screen and (max-width: $break-small) { |
||||
right: 16px; |
||||
} |
||||
|
||||
/* Use the sass mixin */ |
||||
@include screen-sm-max { |
||||
right: 16px; |
||||
} |
||||
|
||||
/* Min width */ |
||||
/* Instead of the media query and sass variable */ |
||||
@media screen and (min-width: $break-large) { |
||||
left: 16px; |
||||
} |
||||
|
||||
/* Use the sass mixin */ |
||||
@include screen-sm-min { |
||||
left: 16px; |
||||
} |
||||
``` |
||||
|
||||
## Takeaways |
||||
|
||||
- Try to avoid using static media queries in your code. |
||||
- Try to use the provided SCSS mixins |
||||
|
||||
### ❌ Don't do this |
||||
|
||||
Don't use static media queries in your code. |
||||
|
||||
```css |
||||
/** |
||||
* Don't do this |
||||
* Static media queries create inconsistency and could break the UI if we want to update them in future |
||||
**/ |
||||
.account-menu { |
||||
@media screen and (min-width: 769px) { |
||||
right: calc((100vw - 80vw) / 2); |
||||
} |
||||
|
||||
@media screen and (min-width: 1281px) { |
||||
right: calc((100vw - 65vw) / 2); |
||||
} |
||||
} |
||||
``` |
||||
|
||||
### ✅ Do this |
||||
|
||||
Do use the provided Sass mixins |
||||
|
||||
```css |
||||
.account-menu { |
||||
@include screen-md-min { |
||||
right: calc((100vw - 80vw) / 2); |
||||
} |
||||
|
||||
@include screen-lg-min { |
||||
right: calc((100vw - 65vw) / 2); |
||||
} |
||||
} |
||||
``` |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,217 @@ |
||||
import { MESSAGE_TYPE } from '../../../shared/constants/app'; |
||||
import { EVENT_NAMES } from '../../../shared/constants/metametrics'; |
||||
import { SECOND } from '../../../shared/constants/time'; |
||||
import createRPCMethodTrackingMiddleware from './createRPCMethodTrackingMiddleware'; |
||||
|
||||
const trackEvent = jest.fn(); |
||||
const metricsState = { participateInMetaMetrics: null }; |
||||
const getMetricsState = () => metricsState; |
||||
|
||||
const handler = createRPCMethodTrackingMiddleware({ |
||||
trackEvent, |
||||
getMetricsState, |
||||
rateLimitSeconds: 1, |
||||
}); |
||||
|
||||
function getNext(timeout = 500) { |
||||
let deferred; |
||||
const promise = new Promise((resolve) => { |
||||
deferred = { |
||||
resolve, |
||||
}; |
||||
}); |
||||
const cb = () => deferred.resolve(); |
||||
let triggerNext; |
||||
setTimeout(() => { |
||||
deferred.resolve(); |
||||
}, timeout); |
||||
return { |
||||
executeMiddlewareStack: async () => { |
||||
if (triggerNext) { |
||||
triggerNext(() => cb()); |
||||
} |
||||
return await deferred.resolve(); |
||||
}, |
||||
promise, |
||||
next: (postReqHandler) => { |
||||
triggerNext = postReqHandler; |
||||
}, |
||||
}; |
||||
} |
||||
|
||||
const waitForSeconds = async (seconds) => |
||||
await new Promise((resolve) => setTimeout(resolve, SECOND * seconds)); |
||||
|
||||
describe('createRPCMethodTrackingMiddleware', () => { |
||||
afterEach(() => { |
||||
jest.resetAllMocks(); |
||||
metricsState.participateInMetaMetrics = null; |
||||
}); |
||||
|
||||
describe('before participateInMetaMetrics is set', () => { |
||||
it('should not track an event for a signature request', async () => { |
||||
const req = { |
||||
method: MESSAGE_TYPE.ETH_SIGN, |
||||
origin: 'some.dapp', |
||||
}; |
||||
|
||||
const res = { |
||||
error: null, |
||||
}; |
||||
const { executeMiddlewareStack, next } = getNext(); |
||||
handler(req, res, next); |
||||
await executeMiddlewareStack(); |
||||
expect(trackEvent).not.toHaveBeenCalled(); |
||||
}); |
||||
}); |
||||
|
||||
describe('participateInMetaMetrics is set to false', () => { |
||||
beforeEach(() => { |
||||
metricsState.participateInMetaMetrics = false; |
||||
}); |
||||
|
||||
it('should not track an event for a signature request', async () => { |
||||
const req = { |
||||
method: MESSAGE_TYPE.ETH_SIGN, |
||||
origin: 'some.dapp', |
||||
}; |
||||
|
||||
const res = { |
||||
error: null, |
||||
}; |
||||
const { executeMiddlewareStack, next } = getNext(); |
||||
handler(req, res, next); |
||||
await executeMiddlewareStack(); |
||||
expect(trackEvent).not.toHaveBeenCalled(); |
||||
}); |
||||
}); |
||||
|
||||
describe('participateInMetaMetrics is set to true', () => { |
||||
beforeEach(() => { |
||||
metricsState.participateInMetaMetrics = true; |
||||
}); |
||||
|
||||
it(`should immediately track a ${EVENT_NAMES.SIGNATURE_REQUESTED} event`, () => { |
||||
const req = { |
||||
method: MESSAGE_TYPE.ETH_SIGN, |
||||
origin: 'some.dapp', |
||||
}; |
||||
|
||||
const res = { |
||||
error: null, |
||||
}; |
||||
const { next } = getNext(); |
||||
handler(req, res, next); |
||||
expect(trackEvent).toHaveBeenCalledTimes(1); |
||||
expect(trackEvent.mock.calls[0][0]).toMatchObject({ |
||||
category: 'inpage_provider', |
||||
event: EVENT_NAMES.SIGNATURE_REQUESTED, |
||||
properties: { signature_type: MESSAGE_TYPE.ETH_SIGN }, |
||||
referrer: { url: 'some.dapp' }, |
||||
}); |
||||
}); |
||||
|
||||
it(`should track a ${EVENT_NAMES.SIGNATURE_APPROVED} event if the user approves`, async () => { |
||||
const req = { |
||||
method: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4, |
||||
origin: 'some.dapp', |
||||
}; |
||||
|
||||
const res = { |
||||
error: null, |
||||
}; |
||||
const { next, executeMiddlewareStack } = getNext(); |
||||
handler(req, res, next); |
||||
await executeMiddlewareStack(); |
||||
expect(trackEvent).toHaveBeenCalledTimes(2); |
||||
expect(trackEvent.mock.calls[1][0]).toMatchObject({ |
||||
category: 'inpage_provider', |
||||
event: EVENT_NAMES.SIGNATURE_APPROVED, |
||||
properties: { signature_type: MESSAGE_TYPE.ETH_SIGN_TYPED_DATA_V4 }, |
||||
referrer: { url: 'some.dapp' }, |
||||
}); |
||||
}); |
||||
|
||||
it(`should track a ${EVENT_NAMES.SIGNATURE_REJECTED} event if the user approves`, async () => { |
||||
const req = { |
||||
method: MESSAGE_TYPE.PERSONAL_SIGN, |
||||
origin: 'some.dapp', |
||||
}; |
||||
|
||||
const res = { |
||||
error: { code: 4001 }, |
||||
}; |
||||
const { next, executeMiddlewareStack } = getNext(); |
||||
handler(req, res, next); |
||||
await executeMiddlewareStack(); |
||||
expect(trackEvent).toHaveBeenCalledTimes(2); |
||||
expect(trackEvent.mock.calls[1][0]).toMatchObject({ |
||||
category: 'inpage_provider', |
||||
event: EVENT_NAMES.SIGNATURE_REJECTED, |
||||
properties: { signature_type: MESSAGE_TYPE.PERSONAL_SIGN }, |
||||
referrer: { url: 'some.dapp' }, |
||||
}); |
||||
}); |
||||
|
||||
it(`should track a ${EVENT_NAMES.PERMISSIONS_APPROVED} event if the user approves`, async () => { |
||||
const req = { |
||||
method: MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS, |
||||
origin: 'some.dapp', |
||||
}; |
||||
|
||||
const res = {}; |
||||
const { next, executeMiddlewareStack } = getNext(); |
||||
handler(req, res, next); |
||||
await executeMiddlewareStack(); |
||||
expect(trackEvent).toHaveBeenCalledTimes(2); |
||||
expect(trackEvent.mock.calls[1][0]).toMatchObject({ |
||||
category: 'inpage_provider', |
||||
event: EVENT_NAMES.PERMISSIONS_APPROVED, |
||||
properties: { method: MESSAGE_TYPE.ETH_REQUEST_ACCOUNTS }, |
||||
referrer: { url: 'some.dapp' }, |
||||
}); |
||||
}); |
||||
|
||||
it(`should never track blocked methods such as ${MESSAGE_TYPE.GET_PROVIDER_STATE}`, () => { |
||||
const req = { |
||||
method: MESSAGE_TYPE.GET_PROVIDER_STATE, |
||||
origin: 'www.notadapp.com', |
||||
}; |
||||
|
||||
const res = { |
||||
error: null, |
||||
}; |
||||
const { next, executeMiddlewareStack } = getNext(); |
||||
handler(req, res, next); |
||||
expect(trackEvent).not.toHaveBeenCalled(); |
||||
executeMiddlewareStack(); |
||||
}); |
||||
|
||||
it(`should only track events when not rate limited`, async () => { |
||||
const req = { |
||||
method: 'eth_chainId', |
||||
origin: 'some.dapp', |
||||
}; |
||||
|
||||
const res = { |
||||
error: null, |
||||
}; |
||||
|
||||
let callCount = 0; |
||||
|
||||
while (callCount < 3) { |
||||
callCount += 1; |
||||
const { next, executeMiddlewareStack } = getNext(); |
||||
handler(req, res, next); |
||||
await executeMiddlewareStack(); |
||||
if (callCount !== 3) { |
||||
await waitForSeconds(0.6); |
||||
} |
||||
} |
||||
|
||||
expect(trackEvent).toHaveBeenCalledTimes(2); |
||||
expect(trackEvent.mock.calls[0][0].properties.method).toBe('eth_chainId'); |
||||
expect(trackEvent.mock.calls[1][0].properties.method).toBe('eth_chainId'); |
||||
}); |
||||
}); |
||||
}); |
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in new issue