diff --git a/redisinsight/ui/src/components/monitor-config/MonitorConfig.tsx b/redisinsight/ui/src/components/monitor-config/MonitorConfig.tsx
index a28f6be69c..5f3b0b61d7 100644
--- a/redisinsight/ui/src/components/monitor-config/MonitorConfig.tsx
+++ b/redisinsight/ui/src/components/monitor-config/MonitorConfig.tsx
@@ -49,6 +49,7 @@ const MonitorConfig = ({ retryDelay = 10000 } : IProps) => {
const newSocket = io(`${getBaseApiUrl()}/monitor`, {
forceNew: true,
query: { instanceId },
+ rejectUnauthorized: false,
})
dispatch(setSocket(newSocket))
let payloads: IMonitorDataPayload[] = []
diff --git a/redisinsight/ui/src/components/monitor/Monitor/Monitor.tsx b/redisinsight/ui/src/components/monitor/Monitor/Monitor.tsx
index 51c46fe9be..92a2dd0005 100644
--- a/redisinsight/ui/src/components/monitor/Monitor/Monitor.tsx
+++ b/redisinsight/ui/src/components/monitor/Monitor/Monitor.tsx
@@ -62,7 +62,7 @@ const Monitor = (props: Props) => {
/>
-
+
Running Profiler will decrease throughput, avoid running it in production databases
diff --git a/tests/e2e/helpers/conf.ts b/tests/e2e/helpers/conf.ts
index 949cd09ee9..47e5c8d48f 100644
--- a/tests/e2e/helpers/conf.ts
+++ b/tests/e2e/helpers/conf.ts
@@ -1,3 +1,6 @@
+import { Chance } from 'chance';
+const chance = new Chance();
+
// Urls for using in the tests
export const commonUrl = process.env.COMMON_URL || 'https://localhost:5000';
@@ -52,3 +55,10 @@ export const invalidOssStandaloneConfig = {
databaseUsername: process.env.OSS_STANDALONE_USERNAME,
databasePassword: process.env.OSS_STANDALONE_PASSWORD
};
+export const ossBigStandaloneConfig = {
+ host: process.env.OSS_STANDALONE_BIG_HOST || 'oss-standalone-big',
+ port: process.env.OSS_STANDALONE_BIG_PORT || '6379',
+ databaseName: process.env.OSS_STANDALONE_BIG_DATABASE_NAME || chance.string({ length: 20 }),
+ databaseUsername: process.env.OSS_STANDALONE_BIG_USERNAME,
+ databasePassword: process.env.OSS_STANDALONE_BIG_PASSWORD
+};
diff --git a/tests/e2e/pageObjects/cli-page.ts b/tests/e2e/pageObjects/cli-page.ts
index 455acf78ba..5fcaa9440e 100644
--- a/tests/e2e/pageObjects/cli-page.ts
+++ b/tests/e2e/pageObjects/cli-page.ts
@@ -91,11 +91,11 @@ export class CliPage {
}
/**
- * Add keys from CLI
- * @param keyCommand The command from cli to add key
- * @param amount The amount of the keys
- * @param keyName The name of the keys. The default value is keyName
- */
+ * Add keys from CLI
+ * @param keyCommand The command from cli to add key
+ * @param amount The amount of the keys
+ * @param keyName The name of the keys. The default value is keyName
+ */
async addKeysFromCli(keyCommand: string, amount: number, keyName = 'keyName'): Promise{
//Open CLI
await t.click(this.cliExpandButton);
@@ -105,4 +105,18 @@ export class CliPage {
await t.pressKey('enter');
await t.click(this.cliCollapseButton);
}
+ /**
+ * Get command result execution
+ * @param command The command for send in CLI
+ */
+ async getSuccessCommandResultFromCli(command: string): Promise{
+ //Open CLI
+ await t.click(this.cliExpandButton);
+ //Add keys
+ await t.typeText(this.cliCommandInput, command, { paste: true });
+ await t.pressKey('enter');
+ const commandResult = await this.cliOutputResponseSuccess.innerText;
+ await t.click(this.cliCollapseButton);
+ return commandResult;
+ }
}
diff --git a/tests/e2e/pageObjects/index.ts b/tests/e2e/pageObjects/index.ts
index e77f470a2a..1810472707 100644
--- a/tests/e2e/pageObjects/index.ts
+++ b/tests/e2e/pageObjects/index.ts
@@ -9,6 +9,7 @@ import { WorkbenchPage } from './workbench-page';
import { DatabaseOverviewPage } from './database-overview-page';
import { HelpCenterPage } from './help-center-page';
import { ShortcutsPage } from './shortcuts-page';
+import { MonitorPage } from './monitor-page';
export {
AddRedisDatabasePage,
@@ -21,5 +22,6 @@ export {
WorkbenchPage,
DatabaseOverviewPage,
HelpCenterPage,
- ShortcutsPage
+ ShortcutsPage,
+ MonitorPage
}
diff --git a/tests/e2e/pageObjects/monitor-page.ts b/tests/e2e/pageObjects/monitor-page.ts
new file mode 100644
index 0000000000..a2b24380d4
--- /dev/null
+++ b/tests/e2e/pageObjects/monitor-page.ts
@@ -0,0 +1,76 @@
+import {Selector, t} from 'testcafe';
+
+export class MonitorPage {
+
+ //------------------------------------------------------------------------------------------
+ //DECLARATION OF TYPES: DOM ELEMENTS and UI COMPONENTS
+ //*Assign the 'Selector' type to any element/component nested within the constructor.
+ //------------------------------------------------------------------------------------------
+
+ expandMonitor: Selector
+ monitorArea: Selector
+ runMonitorToggle: Selector
+ startMonitorButton: Selector
+ clearMonitorButton: Selector
+ monitorIsStoppedText: Selector
+ monitorIsStartedText: Selector
+ hideMonitor: Selector
+ closeMonitor: Selector
+ monitorWarningMessage: Selector
+ monitorCommandLinePart: Selector
+ monitorCommandLineTimestamp: Selector
+
+ constructor() {
+ //-------------------------------------------------------------------------------------------
+ //DECLARATION OF SELECTORS
+ //*Declare all elements/components of the relevant page.
+ //*Target any element/component via data-id, if possible!
+ //*The following categories are ordered alphabetically (Alerts, Buttons, Checkboxes, etc.).
+ //-------------------------------------------------------------------------------------------
+ //BUTTONS
+ this.expandMonitor = Selector('[data-testid=expand-monitor]');
+ this.monitorArea = Selector('[data-testid=monitor]');
+ this.runMonitorToggle = Selector('[data-testid=toggle-run-monitor]');
+ this.startMonitorButton = Selector('[data-testid=start-monitor]');
+ this.clearMonitorButton = Selector('[data-testid=clear-monitor]');
+ this.monitorIsStoppedText = Selector('[data-testid=monitor-stopped]');
+ this.monitorIsStartedText = Selector('[data-testid=monitor-started]');
+ this.hideMonitor = Selector('[data-testid=hide-monitor]');
+ this.closeMonitor = Selector('[data-testid=close-monitor]');
+ this.monitorWarningMessage = Selector('[data-testid=monitor-warning-message]');
+ this.monitorCommandLinePart = Selector('[data-testid=monitor] span');
+ this.monitorCommandLineTimestamp = Selector('[data-testid=monitor] span').withText(/[0-9]{2}:[0-9]{2}:[0-9]{2}.[0-9]{3}/);
+ }
+ /**
+ * Check specific command in Monitor
+ * @param command A command which should be displayed in monitor
+ * @param parameters An arguments which should be displayed in monitor
+ */
+ async checkCommandInMonitorResults(command: string, parameters?: string[]): Promise {
+ const commandArray = command.split(' ');
+ for (const value of commandArray) {
+ await t.expect(this.monitorCommandLinePart.withText(value).exists).ok({timeout: 6000});
+ }
+ if (!!parameters) {
+ for (const argument of parameters) {
+ await t.expect(this.monitorCommandLinePart.withText(argument).exists).ok({timeout: 6000});
+ }
+ }
+ }
+ /**
+ * Start monitor function
+ */
+ async startMonitor(): Promise {
+ await t.click(this.expandMonitor);
+ await t.click(this.startMonitorButton);
+ //Check for "info" command that is sent automatically every 5 seconds from BE side
+ await this.checkCommandInMonitorResults('info');
+ }
+ /**
+ * Stop monitor function
+ */
+ async stopMonitor(): Promise {
+ await t.click(this.runMonitorToggle);
+ await t.expect(this.monitorIsStoppedText.exists).ok('Profiler is stopped text');
+ }
+}
diff --git a/tests/e2e/pageObjects/my-redis-databases-page.ts b/tests/e2e/pageObjects/my-redis-databases-page.ts
index 30737ccbb4..ef92de99cb 100644
--- a/tests/e2e/pageObjects/my-redis-databases-page.ts
+++ b/tests/e2e/pageObjects/my-redis-databases-page.ts
@@ -83,7 +83,7 @@ export class MyRedisDatabasePage {
const count = await dbNames.count;
for(let i = 0; i < count; i++) {
- if((await dbNames.nth(1).innerText || '').includes(dbName)) {
+ if((await dbNames.nth(i).innerText || '').includes(dbName)) {
await t.click(this.deleteDatabaseButton.nth(i));
await t.click(this.confirmDeleteButton);
break;
diff --git a/tests/e2e/tests/critical-path/cli/cli-command-helper.e2e.ts b/tests/e2e/tests/critical-path/cli/cli-command-helper.e2e.ts
index 6f98978098..be3a83a72e 100644
--- a/tests/e2e/tests/critical-path/cli/cli-command-helper.e2e.ts
+++ b/tests/e2e/tests/critical-path/cli/cli-command-helper.e2e.ts
@@ -124,7 +124,7 @@ test('Verify that user can type TS. in Command helper and see commands from Redi
//Select group from list and remeber commands
await cliPage.selectFilterGroupType(COMMAND_GROUP_TIMESERIES);
const commandsFilterCount = await cliPage.cliHelperOutputTitles.count;
- let timeSeriesCommands = [];
+ const timeSeriesCommands = [];
for(let i = 0; i < commandsFilterCount; i++) {
timeSeriesCommands.push(await cliPage.cliHelperOutputTitles.nth(i).textContent);
}
@@ -146,7 +146,7 @@ test('Verify that user can type GRAPH. in Command helper and see auto-suggestion
//Select group from list and remeber commands
await cliPage.selectFilterGroupType(COMMAND_GROUP_GRAPH);
const commandsFilterCount = await cliPage.cliHelperOutputTitles.count;
- let graphCommands = [];
+ const graphCommands = [];
for(let i = 0; i < commandsFilterCount; i++) {
graphCommands.push(await cliPage.cliHelperOutputTitles.nth(i).textContent);
}
diff --git a/tests/e2e/tests/critical-path/monitor/monitor.e2e.ts b/tests/e2e/tests/critical-path/monitor/monitor.e2e.ts
new file mode 100644
index 0000000000..fa99f49fac
--- /dev/null
+++ b/tests/e2e/tests/critical-path/monitor/monitor.e2e.ts
@@ -0,0 +1,90 @@
+import { addNewStandaloneDatabase } from '../../../helpers/database';
+import {
+ MyRedisDatabasePage,
+ UserAgreementPage,
+ AddRedisDatabasePage,
+ CliPage,
+ MonitorPage,
+ WorkbenchPage,
+ BrowserPage
+} from '../../../pageObjects';
+import {
+ commonUrl,
+ ossStandaloneConfig
+} from '../../../helpers/conf';
+import { getRandomKeyName } from '../../../helpers/keys';
+
+const myRedisDatabasePage = new MyRedisDatabasePage();
+const userAgreementPage = new UserAgreementPage();
+const addRedisDatabasePage = new AddRedisDatabasePage();
+const cliPage = new CliPage();
+const monitorPage = new MonitorPage();
+const workbenchPage = new WorkbenchPage();
+const browserPage = new BrowserPage();
+const keyName = `${getRandomKeyName(10)}-key`;
+const keyValue = `${getRandomKeyName(10)}-value`;
+
+fixture.only `Monitor`
+ .meta({ type: 'critical_path' })
+ .page(commonUrl)
+ .beforeEach(async t => {
+ await t.maximizeWindow();
+ await userAgreementPage.acceptLicenseTerms();
+ await t.expect(addRedisDatabasePage.addDatabaseButton.exists).ok('The add redis database view', { timeout: 20000 });
+ await addNewStandaloneDatabase(ossStandaloneConfig);
+ await myRedisDatabasePage.clickOnDBByName(ossStandaloneConfig.databaseName);
+ })
+ .afterEach(async t => {
+ await t.click(myRedisDatabasePage.myRedisDBButton);
+ await myRedisDatabasePage.deleteDatabaseByName(ossStandaloneConfig.databaseName);
+ })
+test
+ .after(async t => {
+ await browserPage.deleteKeyByName(keyName);
+ await t.click(myRedisDatabasePage.myRedisDBButton);
+ await myRedisDatabasePage.deleteDatabaseByName(ossStandaloneConfig.databaseName);
+ })
+ ('Verify that user can work with Monitor', async t => {
+ const command = 'set';
+ //Verify that user can open Monitor
+ await t.click(monitorPage.expandMonitor);
+ //Check that monitor is opened
+ await t.expect(monitorPage.monitorArea.exists).ok('Profiler area');
+ await t.expect(monitorPage.startMonitorButton.exists).ok('Start profiler button');
+ //Verify that user can see message inside Monitor "Running Monitor will decrease throughput, avoid running it in production databases." when opens it for the first time
+ await t.expect(monitorPage.monitorWarningMessage.exists).ok('Profiler warning message');
+ await monitorPage.monitorWarningMessage.withText('Running Profiler will decrease throughput, avoid running it in production databases');
+ //Verify that user can run Monitor by clicking "Run" command in the message inside Monitor
+ await t.click(monitorPage.startMonitorButton);
+ await t.expect(monitorPage.monitorIsStartedText.innerText).eql('Profiler is started.');
+ //Verify that user can see run commands in monitor
+ await cliPage.getSuccessCommandResultFromCli(`${command} ${keyName} ${keyValue}`);
+ await monitorPage.checkCommandInMonitorResults(command, [keyName, keyValue]);
+ });
+test('Verify that user can see the list of all commands from all clients ran for this Redis database in the list of results in Monitor', async t => {
+ //Define commands in different clients
+ const cli_command = 'command';
+ const workbench_command = 'hello';
+ const common_command = 'info';
+ const browser_command = 'dbsize';
+ //Expand Monitor panel
+ await t.click(monitorPage.expandMonitor);
+ //Start monitor (using run button in header)
+ await t.click(monitorPage.runMonitorToggle);
+ //Send command in CLI
+ await cliPage.getSuccessCommandResultFromCli(cli_command);
+ //Check that command from CLI is displayed in monitor
+ await monitorPage.checkCommandInMonitorResults(cli_command);
+ //Refresh the page to send command from Browser client
+ await t.click(browserPage.refreshKeysButton);
+ //Check the command from browser client
+ await monitorPage.checkCommandInMonitorResults(browser_command);
+ //Open Workbench page to create new client
+ await t.click(myRedisDatabasePage.workbenchButton);
+ //Send command in Workbench
+ await workbenchPage.sendCommandInWorkbench(workbench_command);
+ //Check that command from Workbench is displayed in monitor
+ await monitorPage.checkCommandInMonitorResults(workbench_command);
+ //Check the command from common client
+ await monitorPage.checkCommandInMonitorResults(common_command);
+});
diff --git a/tests/e2e/tests/regression/cli/cli-command-helper.e2e.ts b/tests/e2e/tests/regression/cli/cli-command-helper.e2e.ts
index af68bced4e..6994a7486b 100644
--- a/tests/e2e/tests/regression/cli/cli-command-helper.e2e.ts
+++ b/tests/e2e/tests/regression/cli/cli-command-helper.e2e.ts
@@ -16,7 +16,7 @@ const COMMAND_GROUP_HyperLogLog = 'HyperLogLog';
fixture `CLI Command helper`
.meta({ type: 'regression' })
.page(commonUrl)
- .beforeEach(async t => {
+ .beforeEach(async() => {
await acceptLicenseTermsAndAddDatabase(ossStandaloneConfig, ossStandaloneConfig.databaseName);
})
diff --git a/tests/e2e/tests/regression/cli/cli.e2e.ts b/tests/e2e/tests/regression/cli/cli.e2e.ts
index 2e745a2d19..a35ad551c2 100644
--- a/tests/e2e/tests/regression/cli/cli.e2e.ts
+++ b/tests/e2e/tests/regression/cli/cli.e2e.ts
@@ -12,7 +12,7 @@ const common = new Common();
fixture `CLI`
.meta({ type: 'regression' })
.page(commonUrl)
- .beforeEach(async t => {
+ .beforeEach(async() => {
await acceptLicenseTermsAndAddDatabase(ossStandaloneConfig, ossStandaloneConfig.databaseName);
})
test('Verify that user can see CLI is minimized when he clicks the "minimize" button', async t => {
diff --git a/tests/e2e/tests/regression/monitor/monitor.e2e.ts b/tests/e2e/tests/regression/monitor/monitor.e2e.ts
new file mode 100644
index 0000000000..eeaf905a8d
--- /dev/null
+++ b/tests/e2e/tests/regression/monitor/monitor.e2e.ts
@@ -0,0 +1,112 @@
+import { Chance } from 'chance';
+import { addNewStandaloneDatabase } from '../../../helpers/database';
+import {
+ MyRedisDatabasePage,
+ UserAgreementPage,
+ AddRedisDatabasePage,
+ MonitorPage,
+ SettingsPage,
+ BrowserPage
+} from '../../../pageObjects';
+import {
+ commonUrl, ossBigStandaloneConfig,
+ ossStandaloneConfig
+} from '../../../helpers/conf';
+
+const myRedisDatabasePage = new MyRedisDatabasePage();
+const userAgreementPage = new UserAgreementPage();
+const addRedisDatabasePage = new AddRedisDatabasePage();
+const monitorPage = new MonitorPage();
+const settingsPage = new SettingsPage();
+const browserPage = new BrowserPage();
+const chance = new Chance();
+
+fixture.only `Monitor`
+ .meta({ type: 'regression' })
+ .page(commonUrl)
+ .beforeEach(async t => {
+ await t.maximizeWindow();
+ await userAgreementPage.acceptLicenseTerms();
+ await t.expect(addRedisDatabasePage.addDatabaseButton.exists).ok('The add redis database view', { timeout: 20000 });
+ await addNewStandaloneDatabase(ossStandaloneConfig);
+ await myRedisDatabasePage.clickOnDBByName(ossStandaloneConfig.databaseName);
+ })
+ .afterEach(async t => {
+ await t.click(myRedisDatabasePage.myRedisDBButton);
+ await myRedisDatabasePage.deleteDatabaseByName(ossStandaloneConfig.databaseName);
+ })
+test('Verify that when user closes the Monitor by clicking on "Close Monitor" button Monitor stopped', async t => {
+ //Run monitor
+ await monitorPage.startMonitor();
+ //Close Monitor
+ await t.click(monitorPage.closeMonitor);
+ //Verify that monitor is not displayed
+ await t.expect(monitorPage.monitorArea.visible).notOk('Profiler area');
+ //Verify that user open monitor again
+ await t.click(monitorPage.expandMonitor);
+ //Verify that when user reopens Monitor history is not displayed
+ await t.expect(monitorPage.startMonitorButton.visible).ok('Start profiler button');
+});
+test('Verify that Monitor is stopped when user clicks on "Stop" button', async t => {
+ //Run monitor
+ await monitorPage.startMonitor();
+ //Click on Stop Monitor button
+ await t.click(monitorPage.runMonitorToggle);
+ //Check for "Monitor is stopped." text
+ await t.expect(monitorPage.monitorIsStoppedText.innerText).eql('Profiler is stopped.');
+ //Check that no commands are displayed after "Monitor is stopped" text
+ await t.expect(monitorPage.monitorIsStoppedText.nextSibling().exists).notOk('No commands in monitor');
+});
+test('Verify that when user refreshes the page the list of results in Monitor is not saved', async t => {
+ //Run monitor
+ await monitorPage.startMonitor();
+ //Refresh the page
+ await t.eval(() => location.reload(true));
+ //Check that monitor is closed
+ await t.expect(monitorPage.monitorArea.exists).notOk('Monitor area');
+ //Check that monitor area doesn't have any saved results
+ await t.click(monitorPage.expandMonitor);
+ await t.expect(monitorPage.monitorWarningMessage.exists).ok('Warning message in monitor');
+});
+test('Verify that when user clicks on "Clear" button in Monitor, all commands history is removed', async t => {
+ //Run monitor
+ await monitorPage.startMonitor();
+ //Stop Monitor
+ await monitorPage.stopMonitor();
+ //Click on Clear button
+ await t.click(monitorPage.clearMonitorButton);
+ //Check that monitor has start screen
+ await t.expect(monitorPage.startMonitorButton.exists).ok('Start monitor button');
+});
+test
+ .before(async t => {
+ await t.maximizeWindow();
+ await userAgreementPage.acceptLicenseTerms();
+ await t.expect(addRedisDatabasePage.addDatabaseButton.exists).ok('Add Redis database view', { timeout: 20000 });
+ await addNewStandaloneDatabase(ossBigStandaloneConfig);
+ await t.click(myRedisDatabasePage.settingsButton);
+ await t.click(settingsPage.accordionAdvancedSettings);
+ await settingsPage.changeKeysToScanValue('20000000');
+ await t.click(myRedisDatabasePage.myRedisDBButton);
+ await myRedisDatabasePage.clickOnDBByName(ossBigStandaloneConfig.databaseName);
+ })
+ .after(async t => {
+ await t.click(myRedisDatabasePage.settingsButton);
+ await t.click(settingsPage.accordionAdvancedSettings);
+ await settingsPage.changeKeysToScanValue('10000');
+ await t.click(myRedisDatabasePage.myRedisDBButton);
+ await myRedisDatabasePage.deleteDatabaseByName(ossBigStandaloneConfig.databaseName);
+ })
+ ('Verify that user can see monitor results in high DB load', async t => {
+ //Run monitor
+ await monitorPage.startMonitor();
+ //Search by not existed key pattern
+ await browserPage.searchByKeyName(`${chance.string({ length:10 })}*`);
+ //Check that the last child is updated
+ for (let i = 0; i <= 10; i++) {
+ const previousTimestamp = await monitorPage.monitorCommandLineTimestamp.nth(-1).textContent;
+ await t.wait(5500);
+ const nextTimestamp = await monitorPage.monitorCommandLineTimestamp.nth(-1).textContent;
+ await t.expect(previousTimestamp).notEql(nextTimestamp);
+ }
+ });
diff --git a/tests/e2e/tests/regression/workbench/default-scripts-area.e2e.ts b/tests/e2e/tests/regression/workbench/default-scripts-area.e2e.ts
index ccdfd45014..e7e88ac4ce 100644
--- a/tests/e2e/tests/regression/workbench/default-scripts-area.e2e.ts
+++ b/tests/e2e/tests/regression/workbench/default-scripts-area.e2e.ts
@@ -109,8 +109,8 @@ test('Verify that user can see the siblings menu by clicking on page counter ele
await t.expect(workbenchPage.enablementAreaPaginationPopover.visible).ok('The siblings menu is displayed');
const countOfButtons = await workbenchPage.paginationPopoverButtons.count;
for (let i = 0; i < countOfButtons; i++) {
- let popoverButton = workbenchPage.paginationPopoverButtons.nth(i);
- await t.expect(popoverButton.textContent).eql(popoverButtons[i], `The siblings menu button ${popoverButtons[i]} is displayed`);
+ const popoverButton = workbenchPage.paginationPopoverButtons.nth(i);
+ await t.expect(popoverButton.textContent).eql(popoverButtons[i], `The siblings menu button ${popoverButtons[i]} is displayed`);
}
});
test('Verify that user can see the quick navigation section to navigate between siblings under the scrolling content', async t => {
diff --git a/tests/e2e/yarn.lock b/tests/e2e/yarn.lock
index 5bc2a9b1a3..d80bc2eef2 100644
--- a/tests/e2e/yarn.lock
+++ b/tests/e2e/yarn.lock
@@ -1034,7 +1034,7 @@
"@nodelib/fs.scandir" "2.1.4"
fastq "^1.6.0"
-"@types/chance@^1.1.3":
+"@types/chance@1.1.3":
version "1.1.3"
resolved "https://registry.yarnpkg.com/@types/chance/-/chance-1.1.3.tgz#d19fe9391288d60fdccd87632bfc9ab2b4523fea"
integrity sha512-X6c6ghhe4/sQh4XzcZWSFaTAUOda38GQHmq9BUanYkOE/EO7ZrkazwKmtsj3xzTjkLWmwULE++23g3d3CCWaWw==
@@ -1608,7 +1608,7 @@ chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
-chance@^1.1.8:
+chance@1.1.8:
version "1.1.8"
resolved "https://registry.yarnpkg.com/chance/-/chance-1.1.8.tgz#5d6c2b78c9170bf6eb9df7acdda04363085be909"
integrity sha512-v7fi5Hj2VbR6dJEGRWLmJBA83LJMS47pkAbmROFxHWd9qmE1esHRZW8Clf1Fhzr3rjxnNZVCjOEv/ivFxeIMtg==