mirror of
				https://github.com/Unleash/unleash.git
				synced 2025-10-27 11:02:16 +01:00 
			
		
		
		
	refactor: convert auth tests from Cypress to Jest (#864)
* refactor: replace data-test with data-testid * refactor: add Jest tests for auth pages * refactor: remove Cypress tests for auth pages * refactor: remove questionable snapshots * refactor: share test server setup/teardown * refactor: restore auth page flex layout * refactor: use toBeInTheDocument * refactor: change recent data-test attrs to data-testid
This commit is contained in:
		
							parent
							
								
									1132a79f6d
								
							
						
					
					
						commit
						49b8e7329e
					
				
							
								
								
									
										24
									
								
								frontend/.github/workflows/e2e.auth.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										24
									
								
								frontend/.github/workflows/e2e.auth.yml
									
									
									
									
										vendored
									
									
								
							| @ -1,24 +0,0 @@ | ||||
| name: e2e:auth | ||||
| # https://docs.github.com/en/actions/reference/events-that-trigger-workflows | ||||
| on: [deployment_status] | ||||
| jobs: | ||||
|   e2e: | ||||
|     # only runs this job on successful deploy | ||||
|     if: github.event_name == 'deployment_status' && github.event.deployment_status.state == 'success' | ||||
|     runs-on: ubuntu-latest | ||||
|     steps: | ||||
|       - name: Dump GitHub context | ||||
|         env: | ||||
|           GITHUB_CONTEXT: ${{ toJson(github) }} | ||||
|         run: | | ||||
|           echo "$GITHUB_CONTEXT" | ||||
|       - name: Checkout | ||||
|         uses: actions/checkout@v3 | ||||
|       - name: Run Cypress | ||||
|         uses: cypress-io/github-action@v2 | ||||
|         with: | ||||
|           config: baseUrl=${{ github.event.deployment_status.target_url }} | ||||
|           record: true | ||||
|           spec: cypress/integration/auth/auth.spec.ts | ||||
|         env: | ||||
|           CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} | ||||
| @ -1,201 +0,0 @@ | ||||
| /// <reference types="cypress" />
 | ||||
| 
 | ||||
| export {}; | ||||
| 
 | ||||
| describe('auth', () => { | ||||
|     it('renders the password login', () => { | ||||
|         cy.intercept('GET', '/api/admin/**', { | ||||
|             statusCode: 401, | ||||
|             body: { | ||||
|                 defaultHidden: false, | ||||
|                 message: 'You must sign in in order to use Unleash', | ||||
|                 options: [], | ||||
|                 path: '/auth/simple/login', | ||||
|                 type: 'password', | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         cy.visit('/'); | ||||
| 
 | ||||
|         cy.intercept('POST', '/auth/simple/login', req => { | ||||
|             expect(req.body.username).to.equal('admin'); | ||||
|             expect(req.body.password).to.equal('unleash4all'); | ||||
|         }).as('passwordLogin'); | ||||
| 
 | ||||
|         cy.wait(1000); | ||||
|         cy.get('[data-test="LOGIN_EMAIL_ID"]').type('admin'); | ||||
|         cy.get('[data-test="LOGIN_PASSWORD_ID"]').type('unleash4all'); | ||||
|         cy.get("[data-test='LOGIN_BUTTON']").click(); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders does not render password login if defaultHidden is true', () => { | ||||
|         cy.intercept('GET', '/api/admin/**', { | ||||
|             statusCode: 401, | ||||
|             body: { | ||||
|                 defaultHidden: true, | ||||
|                 message: 'You must sign in in order to use Unleash', | ||||
|                 options: [], | ||||
|                 path: '/auth/simple/login', | ||||
|                 type: 'password', | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         cy.visit('/'); | ||||
|         cy.get('[data-test="LOGIN_EMAIL_ID"]').should('not.exist'); | ||||
|         cy.get('[data-test="LOGIN_PASSWORD_ID"]').should('not.exist'); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders google auth when options are specified', () => { | ||||
|         const ssoPath = '/auth/google/login'; | ||||
| 
 | ||||
|         cy.intercept('GET', '/api/admin/**', { | ||||
|             statusCode: 401, | ||||
|             body: { | ||||
|                 defaultHidden: true, | ||||
|                 message: 'You must sign in in order to use Unleash', | ||||
|                 options: [ | ||||
|                     { | ||||
|                         type: 'google', | ||||
|                         message: 'Sign in with Google', | ||||
|                         path: ssoPath, | ||||
|                     }, | ||||
|                 ], | ||||
|                 path: '/auth/simple/login', | ||||
|                 type: 'password', | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         cy.visit('/'); | ||||
|         cy.get('[data-test="LOGIN_EMAIL_ID"]').should('not.exist'); | ||||
|         cy.get('[data-test="LOGIN_PASSWORD_ID"]').should('not.exist'); | ||||
| 
 | ||||
|         cy.get('[data-test="SSO_LOGIN_BUTTON-google"]') | ||||
|             .should('exist') | ||||
|             .should('have.attr', 'href', ssoPath); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders oidc auth when options are specified', () => { | ||||
|         const ssoPath = '/auth/oidc/login'; | ||||
| 
 | ||||
|         cy.intercept('GET', '/api/admin/**', { | ||||
|             statusCode: 401, | ||||
|             body: { | ||||
|                 defaultHidden: true, | ||||
|                 message: 'You must sign in in order to use Unleash', | ||||
|                 options: [ | ||||
|                     { | ||||
|                         type: 'oidc', | ||||
|                         message: 'Sign in with OpenId Connect', | ||||
|                         path: ssoPath, | ||||
|                     }, | ||||
|                 ], | ||||
|                 path: '/auth/simple/login', | ||||
|                 type: 'password', | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         cy.visit('/'); | ||||
|         cy.get('[data-test="LOGIN_EMAIL_ID"]').should('not.exist'); | ||||
|         cy.get('[data-test="LOGIN_PASSWORD_ID"]').should('not.exist'); | ||||
| 
 | ||||
|         cy.get('[data-test="SSO_LOGIN_BUTTON-oidc"]') | ||||
|             .should('exist') | ||||
|             .should('have.attr', 'href', ssoPath); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders saml auth when options are specified', () => { | ||||
|         const ssoPath = '/auth/saml/login'; | ||||
| 
 | ||||
|         cy.intercept('GET', '/api/admin/**', { | ||||
|             statusCode: 401, | ||||
|             body: { | ||||
|                 defaultHidden: true, | ||||
|                 message: 'You must sign in in order to use Unleash', | ||||
|                 options: [ | ||||
|                     { | ||||
|                         type: 'saml', | ||||
|                         message: 'Sign in with SAML 2.0', | ||||
|                         path: ssoPath, | ||||
|                     }, | ||||
|                 ], | ||||
|                 path: '/auth/simple/login', | ||||
|                 type: 'password', | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         cy.visit('/'); | ||||
|         cy.get('[data-test="LOGIN_EMAIL_ID"]').should('not.exist'); | ||||
|         cy.get('[data-test="LOGIN_PASSWORD_ID"]').should('not.exist'); | ||||
| 
 | ||||
|         cy.get('[data-test="SSO_LOGIN_BUTTON-saml"]') | ||||
|             .should('exist') | ||||
|             .should('have.attr', 'href', ssoPath); | ||||
|     }); | ||||
| 
 | ||||
|     it('can visit forgot password when password auth is enabled', () => { | ||||
|         cy.intercept('GET', '/api/admin/**', { | ||||
|             statusCode: 401, | ||||
|             body: { | ||||
|                 defaultHidden: false, | ||||
|                 message: 'You must sign in in order to use Unleash', | ||||
|                 options: [], | ||||
|                 path: '/auth/simple/login', | ||||
|                 type: 'password', | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         cy.visit('/forgotten-password'); | ||||
|         cy.get('[data-test="FORGOTTEN_PASSWORD_FIELD"').type('me@myemail.com'); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders demo auth correctly', () => { | ||||
|         const email = 'hello@hello.com'; | ||||
| 
 | ||||
|         cy.intercept('GET', '/api/admin/**', { | ||||
|             statusCode: 401, | ||||
|             body: { | ||||
|                 defaultHidden: false, | ||||
|                 message: 'You must sign in in order to use Unleash', | ||||
|                 options: [], | ||||
|                 path: '/auth/demo/login', | ||||
|                 type: 'demo', | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         cy.intercept('POST', '/auth/demo/login', req => { | ||||
|             expect(req.body.email).to.equal(email); | ||||
|         }).as('passwordLogin'); | ||||
| 
 | ||||
|         cy.visit('/'); | ||||
|         cy.get('[data-test="LOGIN_EMAIL_ID"]').type(email); | ||||
|         cy.get("[data-test='LOGIN_BUTTON']").click(); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders email auth correctly', () => { | ||||
|         const email = 'hello@hello.com'; | ||||
| 
 | ||||
|         cy.intercept('GET', '/api/admin/**', { | ||||
|             statusCode: 401, | ||||
|             body: { | ||||
|                 defaultHidden: false, | ||||
|                 message: 'You must sign in in order to use Unleash', | ||||
|                 options: [], | ||||
|                 path: '/auth/unsecure/login', | ||||
|                 type: 'unsecure', | ||||
|             }, | ||||
|         }); | ||||
| 
 | ||||
|         cy.intercept('POST', '/auth/unsecure/login', req => { | ||||
|             expect(req.body.email).to.equal(email); | ||||
|         }).as('passwordLogin'); | ||||
| 
 | ||||
|         cy.visit('/'); | ||||
|         cy.get('[data-test="LOGIN_EMAIL_ID"]').type(email); | ||||
|         cy.get("[data-test='LOGIN_BUTTON']").click(); | ||||
|     }); | ||||
| 
 | ||||
|     it('renders invalid token page when token is invalid', () => { | ||||
|         cy.visit('/new-user?token=hellotokenworld'); | ||||
|         cy.get('[data-test="INVALID_TOKEN_BUTTON"]').should('be.visible'); | ||||
|     }); | ||||
| }); | ||||
| @ -42,61 +42,61 @@ describe('feature', () => { | ||||
| 
 | ||||
|     beforeEach(() => { | ||||
|         cy.visit('/'); | ||||
|         cy.get('[data-test="LOGIN_EMAIL_ID"]').type(AUTH_USER); | ||||
|         cy.get('[data-testid="LOGIN_EMAIL_ID"]').type(AUTH_USER); | ||||
| 
 | ||||
|         if (AUTH_PASSWORD) { | ||||
|             cy.get('[data-test="LOGIN_PASSWORD_ID"]').type(AUTH_PASSWORD); | ||||
|             cy.get('[data-testid="LOGIN_PASSWORD_ID"]').type(AUTH_PASSWORD); | ||||
|         } | ||||
| 
 | ||||
|         cy.get("[data-test='LOGIN_BUTTON']").click(); | ||||
|         cy.get("[data-testid='LOGIN_BUTTON']").click(); | ||||
|         // Wait for the login redirect to complete.
 | ||||
|         cy.get('[data-test=HEADER_USER_AVATAR'); | ||||
|         cy.get('[data-testid=HEADER_USER_AVATAR'); | ||||
|     }); | ||||
| 
 | ||||
|     it('can create a feature toggle', () => { | ||||
|         if (document.querySelector("[data-test='CLOSE_SPLASH']")) { | ||||
|             cy.get("[data-test='CLOSE_SPLASH']").click(); | ||||
|         if (document.querySelector("[data-testid='CLOSE_SPLASH']")) { | ||||
|             cy.get("[data-testid='CLOSE_SPLASH']").click(); | ||||
|         } | ||||
| 
 | ||||
|         cy.get('[data-test=NAVIGATE_TO_CREATE_FEATURE').click(); | ||||
|         cy.get('[data-testid=NAVIGATE_TO_CREATE_FEATURE').click(); | ||||
| 
 | ||||
|         cy.intercept('POST', '/api/admin/projects/default/features').as( | ||||
|             'createFeature' | ||||
|         ); | ||||
| 
 | ||||
|         cy.get("[data-test='CF_NAME_ID'").type(featureToggleName); | ||||
|         cy.get("[data-test='CF_DESC_ID'").type('hello-world'); | ||||
|         cy.get("[data-test='CF_CREATE_BTN_ID']").click(); | ||||
|         cy.get("[data-testid='CF_NAME_ID'").type(featureToggleName); | ||||
|         cy.get("[data-testid='CF_DESC_ID'").type('hello-world'); | ||||
|         cy.get("[data-testid='CF_CREATE_BTN_ID']").click(); | ||||
|         cy.wait('@createFeature'); | ||||
|         cy.url().should('include', featureToggleName); | ||||
|     }); | ||||
| 
 | ||||
|     it('gives an error if a toggle exists with the same name', () => { | ||||
|         cy.get('[data-test=NAVIGATE_TO_CREATE_FEATURE').click(); | ||||
|         cy.get('[data-testid=NAVIGATE_TO_CREATE_FEATURE').click(); | ||||
| 
 | ||||
|         cy.intercept('POST', '/api/admin/projects/default/features').as( | ||||
|             'createFeature' | ||||
|         ); | ||||
| 
 | ||||
|         cy.get("[data-test='CF_NAME_ID'").type(featureToggleName); | ||||
|         cy.get("[data-test='CF_DESC_ID'").type('hello-world'); | ||||
|         cy.get("[data-test='CF_CREATE_BTN_ID']").click(); | ||||
|         cy.get("[data-test='INPUT_ERROR_TEXT']").contains( | ||||
|         cy.get("[data-testid='CF_NAME_ID'").type(featureToggleName); | ||||
|         cy.get("[data-testid='CF_DESC_ID'").type('hello-world'); | ||||
|         cy.get("[data-testid='CF_CREATE_BTN_ID']").click(); | ||||
|         cy.get("[data-testid='INPUT_ERROR_TEXT']").contains( | ||||
|             'A feature with this name already exists' | ||||
|         ); | ||||
|     }); | ||||
| 
 | ||||
|     it('gives an error if a toggle name is url unsafe', () => { | ||||
|         cy.get('[data-test=NAVIGATE_TO_CREATE_FEATURE').click(); | ||||
|         cy.get('[data-testid=NAVIGATE_TO_CREATE_FEATURE').click(); | ||||
| 
 | ||||
|         cy.intercept('POST', '/api/admin/projects/default/features').as( | ||||
|             'createFeature' | ||||
|         ); | ||||
| 
 | ||||
|         cy.get("[data-test='CF_NAME_ID'").type('featureToggleUnsafe####$#//'); | ||||
|         cy.get("[data-test='CF_DESC_ID'").type('hello-world'); | ||||
|         cy.get("[data-test='CF_CREATE_BTN_ID']").click(); | ||||
|         cy.get("[data-test='INPUT_ERROR_TEXT']").contains( | ||||
|         cy.get("[data-testid='CF_NAME_ID'").type('featureToggleUnsafe####$#//'); | ||||
|         cy.get("[data-testid='CF_DESC_ID'").type('hello-world'); | ||||
|         cy.get("[data-testid='CF_CREATE_BTN_ID']").click(); | ||||
|         cy.get("[data-testid='INPUT_ERROR_TEXT']").contains( | ||||
|             `"name" must be URL friendly` | ||||
|         ); | ||||
|     }); | ||||
| @ -107,16 +107,16 @@ describe('feature', () => { | ||||
|         ); | ||||
| 
 | ||||
|         cy.wait(1000); | ||||
|         cy.get('[data-test=ROLLOUT_SLIDER_ID') | ||||
|         cy.get('[data-testid=ROLLOUT_SLIDER_ID') | ||||
|             .click() | ||||
|             .type('{leftarrow}'.repeat(20)); | ||||
| 
 | ||||
|         if (ENTERPRISE) { | ||||
|             cy.get('[data-test=ADD_CONSTRAINT_ID]').click(); | ||||
|             cy.get('[data-test=CONSTRAINT_AUTOCOMPLETE_ID]') | ||||
|             cy.get('[data-testid=ADD_CONSTRAINT_ID]').click(); | ||||
|             cy.get('[data-testid=CONSTRAINT_AUTOCOMPLETE_ID]') | ||||
|                 .type('{downArrow}'.repeat(1)) | ||||
|                 .type('{enter}'); | ||||
|             cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); | ||||
|             cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         } | ||||
| 
 | ||||
|         cy.intercept( | ||||
| @ -140,7 +140,7 @@ describe('feature', () => { | ||||
|             } | ||||
|         ).as('addStrategyToFeature'); | ||||
| 
 | ||||
|         cy.get(`[data-test=STRATEGY_FORM_SUBMIT_ID]`).first().click(); | ||||
|         cy.get(`[data-testid=STRATEGY_FORM_SUBMIT_ID]`).first().click(); | ||||
|         cy.wait('@addStrategyToFeature'); | ||||
|     }); | ||||
| 
 | ||||
| @ -150,18 +150,18 @@ describe('feature', () => { | ||||
|         ); | ||||
| 
 | ||||
|         cy.wait(1000); | ||||
|         cy.get('[data-test=ROLLOUT_SLIDER_ID') | ||||
|         cy.get('[data-testid=ROLLOUT_SLIDER_ID') | ||||
|             .click() | ||||
|             .type('{rightArrow}'.repeat(10)); | ||||
| 
 | ||||
|         cy.get('[data-test=FLEXIBLE_STRATEGY_STICKINESS_ID]') | ||||
|         cy.get('[data-testid=FLEXIBLE_STRATEGY_STICKINESS_ID]') | ||||
|             .first() | ||||
|             .click() | ||||
|             .get('[data-test=SELECT_ITEM_ID-sessionId') | ||||
|             .get('[data-testid=SELECT_ITEM_ID-sessionId') | ||||
|             .first() | ||||
|             .click(); | ||||
| 
 | ||||
|         cy.get('[data-test=FLEXIBLE_STRATEGY_GROUP_ID]') | ||||
|         cy.get('[data-testid=FLEXIBLE_STRATEGY_GROUP_ID]') | ||||
|             .first() | ||||
|             .clear() | ||||
|             .type('new-group-id'); | ||||
| @ -186,7 +186,7 @@ describe('feature', () => { | ||||
|             } | ||||
|         ).as('updateStrategy'); | ||||
| 
 | ||||
|         cy.get(`[data-test=STRATEGY_FORM_SUBMIT_ID]`).first().click(); | ||||
|         cy.get(`[data-testid=STRATEGY_FORM_SUBMIT_ID]`).first().click(); | ||||
|         cy.wait('@updateStrategy'); | ||||
|     }); | ||||
| 
 | ||||
| @ -203,9 +203,11 @@ describe('feature', () => { | ||||
|             } | ||||
|         ).as('deleteStrategy'); | ||||
| 
 | ||||
|         cy.get('[data-test=FEATURE_ENVIRONMENT_ACCORDION_development]').click(); | ||||
|         cy.get('[data-test=STRATEGY_FORM_REMOVE_ID]').click(); | ||||
|         cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.get( | ||||
|             '[data-testid=FEATURE_ENVIRONMENT_ACCORDION_development]' | ||||
|         ).click(); | ||||
|         cy.get('[data-testid=STRATEGY_FORM_REMOVE_ID]').click(); | ||||
|         cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.wait('@deleteStrategy'); | ||||
|     }); | ||||
| 
 | ||||
| @ -215,19 +217,19 @@ describe('feature', () => { | ||||
|         ); | ||||
| 
 | ||||
|         if (ENTERPRISE) { | ||||
|             cy.get('[data-test=ADD_CONSTRAINT_ID]').click(); | ||||
|             cy.get('[data-test=CONSTRAINT_AUTOCOMPLETE_ID]') | ||||
|             cy.get('[data-testid=ADD_CONSTRAINT_ID]').click(); | ||||
|             cy.get('[data-testid=CONSTRAINT_AUTOCOMPLETE_ID]') | ||||
|                 .type('{downArrow}'.repeat(1)) | ||||
|                 .type('{enter}'); | ||||
|             cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); | ||||
|             cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         } | ||||
| 
 | ||||
|         cy.get('[data-test=STRATEGY_INPUT_LIST]') | ||||
|         cy.get('[data-testid=STRATEGY_INPUT_LIST]') | ||||
|             .type('user1') | ||||
|             .type('{enter}') | ||||
|             .type('user2') | ||||
|             .type('{enter}'); | ||||
|         cy.get('[data-test=ADD_TO_STRATEGY_INPUT_LIST]').click(); | ||||
|         cy.get('[data-testid=ADD_TO_STRATEGY_INPUT_LIST]').click(); | ||||
| 
 | ||||
|         cy.intercept( | ||||
|             'POST', | ||||
| @ -249,7 +251,7 @@ describe('feature', () => { | ||||
|             } | ||||
|         ).as('addStrategyToFeature'); | ||||
| 
 | ||||
|         cy.get(`[data-test=STRATEGY_FORM_SUBMIT_ID]`).first().click(); | ||||
|         cy.get(`[data-testid=STRATEGY_FORM_SUBMIT_ID]`).first().click(); | ||||
|         cy.wait('@addStrategyToFeature'); | ||||
|     }); | ||||
| 
 | ||||
| @ -278,32 +280,32 @@ describe('feature', () => { | ||||
|             } | ||||
|         ).as('variantCreation'); | ||||
| 
 | ||||
|         cy.get('[data-test=ADD_VARIANT_BUTTON]').click(); | ||||
|         cy.get('[data-testid=ADD_VARIANT_BUTTON]').click(); | ||||
|         cy.wait(1000); | ||||
|         cy.get('[data-test=VARIANT_NAME_INPUT]').type(variantName); | ||||
|         cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.get('[data-testid=VARIANT_NAME_INPUT]').type(variantName); | ||||
|         cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.wait('@variantCreation'); | ||||
|         cy.get('[data-test=ADD_VARIANT_BUTTON]').click(); | ||||
|         cy.get('[data-testid=ADD_VARIANT_BUTTON]').click(); | ||||
|         cy.wait(1000); | ||||
|         cy.get('[data-test=VARIANT_NAME_INPUT]').type(secondVariantName); | ||||
|         cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.get('[data-testid=VARIANT_NAME_INPUT]').type(secondVariantName); | ||||
|         cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.wait('@variantCreation'); | ||||
|     }); | ||||
| 
 | ||||
|     it('can set weight to fixed value for one of the variants', () => { | ||||
|         cy.visit(`/projects/default/features/${featureToggleName}/variants`); | ||||
| 
 | ||||
|         cy.get('[data-test=VARIANT_EDIT_BUTTON]').first().click(); | ||||
|         cy.get('[data-testid=VARIANT_EDIT_BUTTON]').first().click(); | ||||
|         cy.wait(1000); | ||||
|         cy.get('[data-test=VARIANT_NAME_INPUT]') | ||||
|         cy.get('[data-testid=VARIANT_NAME_INPUT]') | ||||
|             .children() | ||||
|             .find('input') | ||||
|             .should('have.attr', 'disabled'); | ||||
|         cy.get('[data-test=VARIANT_WEIGHT_TYPE]') | ||||
|         cy.get('[data-testid=VARIANT_WEIGHT_TYPE]') | ||||
|             .children() | ||||
|             .find('input') | ||||
|             .check(); | ||||
|         cy.get('[data-test=VARIANT_WEIGHT_INPUT]').clear().type('15'); | ||||
|         cy.get('[data-testid=VARIANT_WEIGHT_INPUT]').clear().type('15'); | ||||
| 
 | ||||
|         cy.intercept( | ||||
|             'PATCH', | ||||
| @ -321,9 +323,9 @@ describe('feature', () => { | ||||
|             } | ||||
|         ).as('variantUpdate'); | ||||
| 
 | ||||
|         cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.wait('@variantUpdate'); | ||||
|         cy.get('[data-test=VARIANT_WEIGHT]') | ||||
|         cy.get('[data-testid=VARIANT_WEIGHT]') | ||||
|             .first() | ||||
|             .should('have.text', '15 %'); | ||||
|     }); | ||||
| @ -332,10 +334,10 @@ describe('feature', () => { | ||||
|         const variantName = 'to-be-deleted'; | ||||
| 
 | ||||
|         cy.visit(`/projects/default/features/${featureToggleName}/variants`); | ||||
|         cy.get('[data-test=ADD_VARIANT_BUTTON]').click(); | ||||
|         cy.get('[data-testid=ADD_VARIANT_BUTTON]').click(); | ||||
|         cy.wait(1000); | ||||
|         cy.get('[data-test=VARIANT_NAME_INPUT]').type(variantName); | ||||
|         cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.get('[data-testid=VARIANT_NAME_INPUT]').type(variantName); | ||||
|         cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click(); | ||||
| 
 | ||||
|         cy.intercept( | ||||
|             'PATCH', | ||||
| @ -348,8 +350,8 @@ describe('feature', () => { | ||||
|             } | ||||
|         ).as('delete'); | ||||
| 
 | ||||
|         cy.get(`[data-test=VARIANT_DELETE_BUTTON_${variantName}]`).click(); | ||||
|         cy.get('[data-test=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.get(`[data-testid=VARIANT_DELETE_BUTTON_${variantName}]`).click(); | ||||
|         cy.get('[data-testid=DIALOGUE_CONFIRM_ID]').click(); | ||||
|         cy.wait('@delete'); | ||||
|     }); | ||||
| }); | ||||
|  | ||||
| @ -25,52 +25,52 @@ describe('segments', () => { | ||||
|         cy.session(AUTH_USER, () => { | ||||
|             cy.visit('/'); | ||||
|             cy.wait(1000); | ||||
|             cy.get("[data-test='LOGIN_EMAIL_ID']").type(AUTH_USER); | ||||
|             cy.get("[data-testid='LOGIN_EMAIL_ID']").type(AUTH_USER); | ||||
| 
 | ||||
|             if (AUTH_PASSWORD) { | ||||
|                 cy.get("[data-test='LOGIN_PASSWORD_ID']").type(AUTH_PASSWORD); | ||||
|                 cy.get("[data-testid='LOGIN_PASSWORD_ID']").type(AUTH_PASSWORD); | ||||
|             } | ||||
| 
 | ||||
|             cy.get("[data-test='LOGIN_BUTTON']").click(); | ||||
|             cy.get("[data-testid='LOGIN_BUTTON']").click(); | ||||
|             // Wait for the login redirect to complete.
 | ||||
|             cy.get("[data-test='HEADER_USER_AVATAR']"); | ||||
|             cy.get("[data-testid='HEADER_USER_AVATAR']"); | ||||
|         }); | ||||
| 
 | ||||
|         cy.visit('/segments'); | ||||
|     }); | ||||
| 
 | ||||
|     it('can create a segment', () => { | ||||
|         if (document.querySelector("[data-test='CLOSE_SPLASH']")) { | ||||
|             cy.get("[data-test='CLOSE_SPLASH']").click(); | ||||
|         if (document.querySelector("[data-testid='CLOSE_SPLASH']")) { | ||||
|             cy.get("[data-testid='CLOSE_SPLASH']").click(); | ||||
|         } | ||||
| 
 | ||||
|         cy.get("[data-test='NAVIGATE_TO_CREATE_SEGMENT']").click(); | ||||
|         cy.get("[data-testid='NAVIGATE_TO_CREATE_SEGMENT']").click(); | ||||
| 
 | ||||
|         cy.intercept('POST', '/api/admin/segments').as('createSegment'); | ||||
| 
 | ||||
|         cy.get("[data-test='SEGMENT_NAME_ID']").type(segmentName); | ||||
|         cy.get("[data-test='SEGMENT_DESC_ID']").type('hello-world'); | ||||
|         cy.get("[data-test='SEGMENT_NEXT_BTN_ID']").click(); | ||||
|         cy.get("[data-test='SEGMENT_CREATE_BTN_ID']").click(); | ||||
|         cy.get("[data-testid='SEGMENT_NAME_ID']").type(segmentName); | ||||
|         cy.get("[data-testid='SEGMENT_DESC_ID']").type('hello-world'); | ||||
|         cy.get("[data-testid='SEGMENT_NEXT_BTN_ID']").click(); | ||||
|         cy.get("[data-testid='SEGMENT_CREATE_BTN_ID']").click(); | ||||
|         cy.wait('@createSegment'); | ||||
|         cy.contains(segmentName); | ||||
|     }); | ||||
| 
 | ||||
|     it('gives an error if a segment exists with the same name', () => { | ||||
|         cy.get("[data-test='NAVIGATE_TO_CREATE_SEGMENT']").click(); | ||||
|         cy.get("[data-testid='NAVIGATE_TO_CREATE_SEGMENT']").click(); | ||||
| 
 | ||||
|         cy.get("[data-test='SEGMENT_NAME_ID']").type(segmentName); | ||||
|         cy.get("[data-test='SEGMENT_NEXT_BTN_ID']").should('be.disabled'); | ||||
|         cy.get("[data-test='INPUT_ERROR_TEXT']").contains( | ||||
|         cy.get("[data-testid='SEGMENT_NAME_ID']").type(segmentName); | ||||
|         cy.get("[data-testid='SEGMENT_NEXT_BTN_ID']").should('be.disabled'); | ||||
|         cy.get("[data-testid='INPUT_ERROR_TEXT']").contains( | ||||
|             'Segment name already exists' | ||||
|         ); | ||||
|     }); | ||||
| 
 | ||||
|     it('can delete a segment', () => { | ||||
|         cy.get(`[data-test='SEGMENT_DELETE_BTN_ID_${segmentName}']`).click(); | ||||
|         cy.get(`[data-testid='SEGMENT_DELETE_BTN_ID_${segmentName}']`).click(); | ||||
| 
 | ||||
|         cy.get("[data-test='SEGMENT_DIALOG_NAME_ID']").type(segmentName); | ||||
|         cy.get("[data-test='DIALOGUE_CONFIRM_ID'").click(); | ||||
|         cy.get("[data-testid='SEGMENT_DIALOG_NAME_ID']").type(segmentName); | ||||
|         cy.get("[data-testid='DIALOGUE_CONFIRM_ID'").click(); | ||||
| 
 | ||||
|         cy.contains(segmentName).should('not.exist'); | ||||
|     }); | ||||
|  | ||||
| @ -68,6 +68,7 @@ | ||||
|     "http-proxy-middleware": "2.0.4", | ||||
|     "immer": "^9.0.12", | ||||
|     "lodash.clonedeep": "4.5.0", | ||||
|     "msw": "^0.39.2", | ||||
|     "prettier": "2.6.1", | ||||
|     "prop-types": "15.8.1", | ||||
|     "react": "17.0.2", | ||||
|  | ||||
| @ -247,7 +247,7 @@ export const ApiTokenList = () => { | ||||
|                                                 '/admin/api/create-token' | ||||
|                                             ) | ||||
|                                         } | ||||
|                                         data-test={CREATE_API_TOKEN_BUTTON} | ||||
|                                         data-testid={CREATE_API_TOKEN_BUTTON} | ||||
|                                     > | ||||
|                                         New API token | ||||
|                                     </Button> | ||||
|  | ||||
| @ -81,7 +81,7 @@ const Dialogue: React.FC<IDialogue> = ({ | ||||
|                                     onClick={handleClick} | ||||
|                                     autoFocus={!formId} | ||||
|                                     disabled={disabledPrimaryButton} | ||||
|                                     data-test={DIALOGUE_CONFIRM_ID} | ||||
|                                     data-testid={DIALOGUE_CONFIRM_ID} | ||||
|                                     type={formId ? 'submit' : 'button'} | ||||
|                                 > | ||||
|                                     {primaryButtonText || "Yes, I'm sure"} | ||||
|  | ||||
| @ -52,7 +52,7 @@ const GeneralSelect: React.FC<ISelectMenuProps> = ({ | ||||
|                 key={option.key} | ||||
|                 value={option.key} | ||||
|                 title={option.title || ''} | ||||
|                 data-test={`${SELECT_ITEM_ID}-${option.label}`} | ||||
|                 data-testid={`${SELECT_ITEM_ID}-${option.label}`} | ||||
|                 disabled={option.disabled} | ||||
|             > | ||||
|                 {option.label} | ||||
|  | ||||
| @ -48,7 +48,7 @@ const Input = ({ | ||||
|                 onChange={onChange} | ||||
|                 FormHelperTextProps={{ | ||||
|                     // @ts-expect-error
 | ||||
|                     ['data-test']: INPUT_ERROR_TEXT, | ||||
|                     ['data-testid']: INPUT_ERROR_TEXT, | ||||
|                     classes: { | ||||
|                         root: styles.helperText, | ||||
|                     }, | ||||
|  | ||||
| @ -29,7 +29,7 @@ export const SidebarModal = ({ | ||||
|             aria-label={label} | ||||
|             BackdropComponent={Backdrop} | ||||
|             BackdropProps={{ timeout: TRANSITION_DURATION }} | ||||
|             data-test={SIDEBAR_MODAL_ID} | ||||
|             data-testid={SIDEBAR_MODAL_ID} | ||||
|         > | ||||
|             <Fade timeout={TRANSITION_DURATION} in={open}> | ||||
|                 <div className={styles.modal}>{children}</div> | ||||
|  | ||||
| @ -80,7 +80,7 @@ export const FormButtons = ({ | ||||
| }) => ( | ||||
|     <div> | ||||
|         <Button | ||||
|             data-test={primaryButtonTestId} | ||||
|             data-testid={primaryButtonTestId} | ||||
|             type="submit" | ||||
|             color="primary" | ||||
|             variant="contained" | ||||
|  | ||||
| @ -41,7 +41,7 @@ const SelectMenu: React.FC<ISelectMenuProps> = ({ | ||||
|                 key={option.key} | ||||
|                 value={option.key} | ||||
|                 title={option.title || ''} | ||||
|                 data-test={`${SELECT_ITEM_ID}-${option.label}`} | ||||
|                 data-testid={`${SELECT_ITEM_ID}-${option.label}`} | ||||
|             > | ||||
|                 {option.label} | ||||
|             </MenuItem> | ||||
|  | ||||
| @ -105,7 +105,7 @@ const CreateFeature = () => { | ||||
|                     name="Feature" | ||||
|                     permission={CREATE_FEATURE} | ||||
|                     projectId={project} | ||||
|                     data-test={CF_CREATE_BTN_ID} | ||||
|                     data-testid={CF_CREATE_BTN_ID} | ||||
|                 /> | ||||
|             </FeatureForm> | ||||
|         </FormTemplate> | ||||
|  | ||||
| @ -32,7 +32,7 @@ export const CreateFeatureButton = ({ | ||||
|                     <IconButton | ||||
|                         component={Link} | ||||
|                         to={createFeature.path} | ||||
|                         data-test={NAVIGATE_TO_CREATE_FEATURE} | ||||
|                         data-testid={NAVIGATE_TO_CREATE_FEATURE} | ||||
|                         disabled={!createFeature.access} | ||||
|                     > | ||||
|                         <Add titleAccess="New" /> | ||||
| @ -45,7 +45,7 @@ export const CreateFeatureButton = ({ | ||||
|                     color="primary" | ||||
|                     variant="contained" | ||||
|                     component={Link} | ||||
|                     data-test={NAVIGATE_TO_CREATE_FEATURE} | ||||
|                     data-testid={NAVIGATE_TO_CREATE_FEATURE} | ||||
|                     disabled={!createFeature.access} | ||||
|                     className={classnames({ skeleton: loading })} | ||||
|                 > | ||||
|  | ||||
| @ -84,7 +84,7 @@ const FeatureForm: React.FC<IFeatureToggleForm> = ({ | ||||
|                     onFocus={() => clearErrors()} | ||||
|                     value={name} | ||||
|                     onChange={e => setName(trim(e.target.value))} | ||||
|                     data-test={CF_NAME_ID} | ||||
|                     data-testid={CF_NAME_ID} | ||||
|                     onBlur={validateToggleName} | ||||
|                 /> | ||||
|                 <p className={styles.inputDescription}> | ||||
| @ -97,7 +97,7 @@ const FeatureForm: React.FC<IFeatureToggleForm> = ({ | ||||
|                     label={'Toggle type'} | ||||
|                     id="feature-type-select" | ||||
|                     editable | ||||
|                     data-test={CF_TYPE_ID} | ||||
|                     data-testid={CF_TYPE_ID} | ||||
|                     IconComponent={KeyboardArrowDownOutlined} | ||||
|                     className={styles.selectInput} | ||||
|                 /> | ||||
| @ -137,7 +137,7 @@ const FeatureForm: React.FC<IFeatureToggleForm> = ({ | ||||
|                     label="Description" | ||||
|                     placeholder="A short description of the feature toggle" | ||||
|                     value={description} | ||||
|                     data-test={CF_DESC_ID} | ||||
|                     data-testid={CF_DESC_ID} | ||||
|                     onChange={e => setDescription(e.target.value)} | ||||
|                 /> | ||||
|                 <FormControl className={styles.input}> | ||||
|  | ||||
| @ -135,7 +135,7 @@ export const FeatureStrategyForm = ({ | ||||
|                     color="primary" | ||||
|                     type="submit" | ||||
|                     disabled={loading || !hasValidConstraints} | ||||
|                     data-test={STRATEGY_FORM_SUBMIT_ID} | ||||
|                     data-testid={STRATEGY_FORM_SUBMIT_ID} | ||||
|                 > | ||||
|                     Save strategy | ||||
|                 </PermissionButton> | ||||
|  | ||||
| @ -68,7 +68,7 @@ export const FeatureStrategyRemove = ({ | ||||
|                         environmentId={environmentId} | ||||
|                         disabled={disabled} | ||||
|                         permission={DELETE_FEATURE_STRATEGY} | ||||
|                         data-test={STRATEGY_FORM_REMOVE_ID} | ||||
|                         data-testid={STRATEGY_FORM_REMOVE_ID} | ||||
|                         type="button" | ||||
|                     > | ||||
|                         <Delete titleAccess="Delete strategy" /> | ||||
| @ -81,7 +81,7 @@ export const FeatureStrategyRemove = ({ | ||||
|                         environmentId={environmentId} | ||||
|                         disabled={disabled} | ||||
|                         permission={DELETE_FEATURE_STRATEGY} | ||||
|                         data-test={STRATEGY_FORM_REMOVE_ID} | ||||
|                         data-testid={STRATEGY_FORM_REMOVE_ID} | ||||
|                         color="secondary" | ||||
|                         variant="text" | ||||
|                         type="button" | ||||
|  | ||||
| @ -89,7 +89,7 @@ const FeatureOverviewEnvironment = ({ | ||||
|         <div className={styles.featureOverviewEnvironment}> | ||||
|             <Accordion | ||||
|                 style={{ boxShadow: 'none' }} | ||||
|                 data-test={`${FEATURE_ENVIRONMENT_ACCORDION}_${env.name}`} | ||||
|                 data-testid={`${FEATURE_ENVIRONMENT_ACCORDION}_${env.name}`} | ||||
|             > | ||||
|                 <AccordionSummary | ||||
|                     className={styles.accordionHeader} | ||||
|  | ||||
| @ -277,7 +277,7 @@ export const AddVariant = ({ | ||||
|                     type="name" | ||||
|                     disabled={editing} | ||||
|                     onChange={setVariantValue} | ||||
|                     data-test={'VARIANT_NAME_INPUT'} | ||||
|                     data-testid={'VARIANT_NAME_INPUT'} | ||||
|                 /> | ||||
|                 <br /> | ||||
|                 <Grid container> | ||||
| @ -299,7 +299,7 @@ export const AddVariant = ({ | ||||
|                                                 projectId={projectId} | ||||
|                                                 name="weightType" | ||||
|                                                 checked={isFixWeight} | ||||
|                                                 data-test={ | ||||
|                                                 data-testid={ | ||||
|                                                     'VARIANT_WEIGHT_TYPE' | ||||
|                                                 } | ||||
|                                                 onChange={setVariantWeightType} | ||||
| @ -320,7 +320,7 @@ export const AddVariant = ({ | ||||
|                                     id="weight" | ||||
|                                     label="Weight" | ||||
|                                     name="weight" | ||||
|                                     data-test={'VARIANT_WEIGHT_INPUT'} | ||||
|                                     data-testid={'VARIANT_WEIGHT_INPUT'} | ||||
|                                     InputProps={{ | ||||
|                                         endAdornment: ( | ||||
|                                             <InputAdornment position="start"> | ||||
| @ -373,7 +373,7 @@ export const AddVariant = ({ | ||||
|                             className={commonStyles.fullWidth} | ||||
|                             value={payload.value} | ||||
|                             onChange={onPayload} | ||||
|                             data-test={'VARIANT_PAYLOAD_VALUE'} | ||||
|                             data-testid={'VARIANT_PAYLOAD_VALUE'} | ||||
|                             placeholder={ | ||||
|                                 payload.type === 'json' | ||||
|                                     ? '{ "hello": "world" }' | ||||
|  | ||||
| @ -292,7 +292,7 @@ const FeatureOverviewVariants = () => { | ||||
|                         setShowAddVariant(true); | ||||
|                     }} | ||||
|                     className={styles.addVariantButton} | ||||
|                     data-test={'ADD_VARIANT_BUTTON'} | ||||
|                     data-testid={'ADD_VARIANT_BUTTON'} | ||||
|                     permission={UPDATE_FEATURE_VARIANTS} | ||||
|                     projectId={projectId} | ||||
|                 > | ||||
|  | ||||
| @ -23,7 +23,7 @@ const FeatureVariantListItem = ({ | ||||
| 
 | ||||
|     return ( | ||||
|         <TableRow> | ||||
|             <TableCell data-test={'VARIANT_NAME'}>{variant.name}</TableCell> | ||||
|             <TableCell data-testid={'VARIANT_NAME'}>{variant.name}</TableCell> | ||||
|             <TableCell className={styles.chipContainer}> | ||||
|                 <ConditionallyRender | ||||
|                     condition={Boolean(variant.payload)} | ||||
| @ -43,10 +43,10 @@ const FeatureVariantListItem = ({ | ||||
|                     } | ||||
|                 /> | ||||
|             </TableCell> | ||||
|             <TableCell data-test={'VARIANT_WEIGHT'}> | ||||
|             <TableCell data-testid={'VARIANT_WEIGHT'}> | ||||
|                 {variant.weight / 10.0} % | ||||
|             </TableCell> | ||||
|             <TableCell data-test={'VARIANT_WEIGHT_TYPE'}> | ||||
|             <TableCell data-testid={'VARIANT_WEIGHT_TYPE'}> | ||||
|                 {variant.weightType === FIX ? 'Fix' : 'Variable'} | ||||
|             </TableCell> | ||||
|             <ConditionallyRender | ||||
| @ -55,13 +55,13 @@ const FeatureVariantListItem = ({ | ||||
|                     <TableCell className={styles.actions}> | ||||
|                         <div className={styles.actionsContainer}> | ||||
|                             <IconButton | ||||
|                                 data-test={'VARIANT_EDIT_BUTTON'} | ||||
|                                 data-testid={'VARIANT_EDIT_BUTTON'} | ||||
|                                 onClick={() => editVariant(variant.name)} | ||||
|                             > | ||||
|                                 <Edit /> | ||||
|                             </IconButton> | ||||
|                             <IconButton | ||||
|                                 data-test={`VARIANT_DELETE_BUTTON_${variant.name}`} | ||||
|                                 data-testid={`VARIANT_DELETE_BUTTON_${variant.name}`} | ||||
|                                 onClick={e => { | ||||
|                                     e.stopPropagation(); | ||||
|                                     setDelDialog({ | ||||
|  | ||||
| @ -117,7 +117,7 @@ const StrategyConstraintInputField = ({ | ||||
|                                 multiple | ||||
|                                 size="small" | ||||
|                                 options={options} | ||||
|                                 data-test={CONSTRAINT_AUTOCOMPLETE_ID} | ||||
|                                 data-testid={CONSTRAINT_AUTOCOMPLETE_ID} | ||||
|                                 value={values || []} | ||||
|                                 getOptionLabel={option => option.label} | ||||
|                                 onBlur={onBlur} | ||||
|  | ||||
| @ -104,7 +104,7 @@ const FlexibleStrategy = ({ | ||||
|                     options={stickinessOptions} | ||||
|                     value={stickiness} | ||||
|                     disabled={!editable} | ||||
|                     data-test={FLEXIBLE_STRATEGY_STICKINESS_ID} | ||||
|                     data-testid={FLEXIBLE_STRATEGY_STICKINESS_ID} | ||||
|                     onChange={e => | ||||
|                         onUpdate('stickiness')(e, e.target.value as number) | ||||
|                     } | ||||
| @ -136,7 +136,7 @@ const FlexibleStrategy = ({ | ||||
|                     value={groupId || ''} | ||||
|                     disabled={!editable} | ||||
|                     onChange={e => onUpdate('groupId')(e, e.target.value)} | ||||
|                     data-test={FLEXIBLE_STRATEGY_GROUP_ID} | ||||
|                     data-testid={FLEXIBLE_STRATEGY_GROUP_ID} | ||||
|                 /> | ||||
|             </div> | ||||
|         </div> | ||||
|  | ||||
| @ -101,7 +101,7 @@ const RolloutSlider = ({ | ||||
|                 getAriaValueText={valuetext} | ||||
|                 aria-labelledby="discrete-slider-always" | ||||
|                 step={1} | ||||
|                 data-test={ROLLOUT_SLIDER_ID} | ||||
|                 data-testid={ROLLOUT_SLIDER_ID} | ||||
|                 marks={marks} | ||||
|                 onChange={onChange} | ||||
|                 valueLabelDisplay="on" | ||||
|  | ||||
| @ -100,12 +100,12 @@ const StrategyInputList = ({ | ||||
|                             onChange={onChange} | ||||
|                             // @ts-expect-error
 | ||||
|                             onKeyDown={onKeyDown} | ||||
|                             data-test={STRATEGY_INPUT_LIST} | ||||
|                             data-testid={STRATEGY_INPUT_LIST} | ||||
|                         /> | ||||
|                         {/* @ts-expect-error */} | ||||
|                         <Button | ||||
|                             onClick={setValue} | ||||
|                             data-test={ADD_TO_STRATEGY_INPUT_LIST} | ||||
|                             data-testid={ADD_TO_STRATEGY_INPUT_LIST} | ||||
|                             color="secondary" | ||||
|                             startIcon={<Add />} | ||||
|                         > | ||||
|  | ||||
| @ -97,7 +97,7 @@ export const CreateSegment = () => { | ||||
|                     name="segment" | ||||
|                     permission={CREATE_SEGMENT} | ||||
|                     disabled={!hasValidConstraints || atSegmentValuesLimit} | ||||
|                     data-test={SEGMENT_CREATE_BTN_ID} | ||||
|                     data-testid={SEGMENT_CREATE_BTN_ID} | ||||
|                 /> | ||||
|             </SegmentForm> | ||||
|         </FormTemplate> | ||||
|  | ||||
| @ -99,7 +99,7 @@ export const EditSegment = () => { | ||||
|                 <UpdateButton | ||||
|                     permission={UPDATE_SEGMENT} | ||||
|                     disabled={!hasValidConstraints || atSegmentValuesLimit} | ||||
|                     data-test={SEGMENT_SAVE_BTN_ID} | ||||
|                     data-testid={SEGMENT_SAVE_BTN_ID} | ||||
|                 /> | ||||
|             </SegmentForm> | ||||
|         </FormTemplate> | ||||
|  | ||||
| @ -55,7 +55,7 @@ export const SegmentDeleteConfirm = ({ | ||||
|                     value={confirmName} | ||||
|                     label="Segment name" | ||||
|                     className={styles.deleteInput} | ||||
|                     data-test={SEGMENT_DIALOG_NAME_ID} | ||||
|                     data-testid={SEGMENT_DIALOG_NAME_ID} | ||||
|                 /> | ||||
|             </form> | ||||
|         </Dialogue> | ||||
|  | ||||
| @ -48,7 +48,7 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({ | ||||
|                     errorText={errors.name} | ||||
|                     autoFocus | ||||
|                     required | ||||
|                     data-test={SEGMENT_NAME_ID} | ||||
|                     data-testid={SEGMENT_NAME_ID} | ||||
|                 /> | ||||
|                 <p className={styles.inputDescription}> | ||||
|                     What is the segment description? | ||||
| @ -60,7 +60,7 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({ | ||||
|                     onChange={e => setDescription(e.target.value)} | ||||
|                     error={Boolean(errors.description)} | ||||
|                     errorText={errors.description} | ||||
|                     data-test={SEGMENT_DESC_ID} | ||||
|                     data-testid={SEGMENT_DESC_ID} | ||||
|                 /> | ||||
|             </div> | ||||
|             <div className={styles.buttonContainer}> | ||||
| @ -70,7 +70,7 @@ export const SegmentFormStepOne: React.FC<ISegmentFormPartOneProps> = ({ | ||||
|                     color="primary" | ||||
|                     onClick={() => setCurrentStep(2)} | ||||
|                     disabled={name.length === 0 || Boolean(errors.name)} | ||||
|                     data-test={SEGMENT_NEXT_BTN_ID} | ||||
|                     data-testid={SEGMENT_NEXT_BTN_ID} | ||||
|                 > | ||||
|                     Next | ||||
|                 </Button> | ||||
|  | ||||
| @ -102,7 +102,7 @@ export const SegmentsList = () => { | ||||
|                         <PermissionButton | ||||
|                             onClick={() => history.push('/segments/create')} | ||||
|                             permission={CREATE_SEGMENT} | ||||
|                             data-test={NAVIGATE_TO_CREATE_SEGMENT} | ||||
|                             data-testid={NAVIGATE_TO_CREATE_SEGMENT} | ||||
|                         > | ||||
|                             New Segment | ||||
|                         </PermissionButton> | ||||
|  | ||||
| @ -83,7 +83,7 @@ export const SegmentListItem = ({ | ||||
|                         setDelDialog(true); | ||||
|                     }} | ||||
|                     permission={ADMIN} | ||||
|                     data-test={`${SEGMENT_DELETE_BTN_ID}_${name}`} | ||||
|                     data-testid={`${SEGMENT_DELETE_BTN_ID}_${name}`} | ||||
|                 > | ||||
|                     <Delete /> | ||||
|                 </PermissionIconButton> | ||||
|  | ||||
| @ -73,7 +73,7 @@ export const SplashPageEnvironmentsContent: React.FC< | ||||
|                     <IconButton | ||||
|                         className={styles.closeButton} | ||||
|                         onClick={onClose} | ||||
|                         data-test={CLOSE_SPLASH} | ||||
|                         data-testid={CLOSE_SPLASH} | ||||
|                     > | ||||
|                         <CloseOutlined titleAccess="Close" /> | ||||
|                     </IconButton> | ||||
|  | ||||
| @ -69,7 +69,7 @@ export const StrategiesList = () => { | ||||
|                     condition={smallScreen} | ||||
|                     show={ | ||||
|                         <PermissionIconButton | ||||
|                             data-test={ADD_NEW_STRATEGY_ID} | ||||
|                             data-testid={ADD_NEW_STRATEGY_ID} | ||||
|                             onClick={() => history.push('/strategies/create')} | ||||
|                             permission={CREATE_STRATEGY} | ||||
|                         > | ||||
| @ -81,7 +81,7 @@ export const StrategiesList = () => { | ||||
|                             onClick={() => history.push('/strategies/create')} | ||||
|                             color="primary" | ||||
|                             permission={CREATE_STRATEGY} | ||||
|                             data-test={ADD_NEW_STRATEGY_ID} | ||||
|                             data-testid={ADD_NEW_STRATEGY_ID} | ||||
|                         > | ||||
|                             New strategy | ||||
|                         </PermissionButton> | ||||
|  | ||||
| @ -42,7 +42,7 @@ exports[`renders correctly with one strategy 1`] = ` | ||||
|         > | ||||
|           <button | ||||
|             className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary" | ||||
|             data-test="ADD_NEW_STRATEGY_ID" | ||||
|             data-testid="ADD_NEW_STRATEGY_ID" | ||||
|             disabled={false} | ||||
|             onBlur={[Function]} | ||||
|             onClick={[Function]} | ||||
| @ -317,7 +317,7 @@ exports[`renders correctly with one strategy without permissions 1`] = ` | ||||
|         > | ||||
|           <button | ||||
|             className="MuiButtonBase-root MuiButton-root MuiButton-contained MuiButton-containedPrimary" | ||||
|             data-test="ADD_NEW_STRATEGY_ID" | ||||
|             data-testid="ADD_NEW_STRATEGY_ID" | ||||
|             disabled={false} | ||||
|             onBlur={[Function]} | ||||
|             onClick={[Function]} | ||||
|  | ||||
| @ -0,0 +1,135 @@ | ||||
| import Authentication from 'component/user/Authentication/Authentication'; | ||||
| import { render, screen } from '@testing-library/react'; | ||||
| import { | ||||
|     LOGIN_PASSWORD_ID, | ||||
|     LOGIN_EMAIL_ID, | ||||
|     LOGIN_BUTTON, | ||||
|     AUTH_PAGE_ID, | ||||
|     SSO_LOGIN_BUTTON, | ||||
| } from 'utils/testIds'; | ||||
| import React from 'react'; | ||||
| import { TestContext } from 'utils/testContext'; | ||||
| import { testServerSetup, testServerRoute } from 'utils/testServer'; | ||||
| 
 | ||||
| const server = testServerSetup(); | ||||
| 
 | ||||
| test('should render password auth', async () => { | ||||
|     testServerRoute(server, '*', { | ||||
|         defaultHidden: false, | ||||
|         message: 'You must sign in in order to use Unleash', | ||||
|         path: '/auth/simple/login', | ||||
|         type: 'password', | ||||
|         options: [], | ||||
|     }); | ||||
| 
 | ||||
|     render( | ||||
|         <TestContext> | ||||
|             <Authentication redirect="/" /> | ||||
|         </TestContext> | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByTestId(AUTH_PAGE_ID); | ||||
|     expect(screen.getByTestId(LOGIN_EMAIL_ID)).toBeInTheDocument(); | ||||
|     expect(screen.getByTestId(LOGIN_PASSWORD_ID)).toBeInTheDocument(); | ||||
|     expect(screen.getByTestId(LOGIN_BUTTON)).toBeInTheDocument(); | ||||
| }); | ||||
| 
 | ||||
| test('should not render password auth if defaultHidden is true', async () => { | ||||
|     testServerRoute(server, '*', { | ||||
|         defaultHidden: true, | ||||
|         message: 'You must sign in in order to use Unleash', | ||||
|         path: '/auth/simple/login', | ||||
|         type: 'password', | ||||
|         options: [], | ||||
|     }); | ||||
| 
 | ||||
|     render( | ||||
|         <TestContext> | ||||
|             <Authentication redirect="/" /> | ||||
|         </TestContext> | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByTestId(AUTH_PAGE_ID); | ||||
|     expect(screen.queryByTestId(LOGIN_EMAIL_ID)).not.toBeInTheDocument(); | ||||
|     expect(screen.queryByTestId(LOGIN_PASSWORD_ID)).not.toBeInTheDocument(); | ||||
|     expect(screen.queryByTestId(LOGIN_BUTTON)).not.toBeInTheDocument(); | ||||
| }); | ||||
| 
 | ||||
| test('should render demo auth', async () => { | ||||
|     testServerRoute(server, '*', { | ||||
|         defaultHidden: false, | ||||
|         message: 'You must sign in in order to use Unleash', | ||||
|         path: '/auth/demo/login', | ||||
|         type: 'demo', | ||||
|         options: [], | ||||
|     }); | ||||
| 
 | ||||
|     render( | ||||
|         <TestContext> | ||||
|             <Authentication redirect="/" /> | ||||
|         </TestContext> | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByTestId(AUTH_PAGE_ID); | ||||
|     expect(screen.getByTestId(LOGIN_EMAIL_ID)).toBeInTheDocument(); | ||||
|     expect(screen.queryByTestId(LOGIN_PASSWORD_ID)).not.toBeInTheDocument(); | ||||
|     expect(screen.getByTestId(LOGIN_BUTTON)).toBeInTheDocument(); | ||||
| }); | ||||
| 
 | ||||
| test('should render email auth', async () => { | ||||
|     testServerRoute(server, '*', { | ||||
|         defaultHidden: false, | ||||
|         message: 'You must sign in in order to use Unleash', | ||||
|         path: '/auth/unsecure/login', | ||||
|         type: 'unsecure', | ||||
|         options: [], | ||||
|     }); | ||||
| 
 | ||||
|     render( | ||||
|         <TestContext> | ||||
|             <Authentication redirect="/" /> | ||||
|         </TestContext> | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByTestId(AUTH_PAGE_ID); | ||||
|     expect(screen.getByTestId(LOGIN_EMAIL_ID)).toBeInTheDocument(); | ||||
|     expect(screen.queryByTestId(LOGIN_PASSWORD_ID)).not.toBeInTheDocument(); | ||||
|     expect(screen.getByTestId(LOGIN_BUTTON)).toBeInTheDocument(); | ||||
| }); | ||||
| 
 | ||||
| test('should render Google auth', async () => { | ||||
|     await testSSOAuthOption('google'); | ||||
| }); | ||||
| 
 | ||||
| test('should render OIDC auth', async () => { | ||||
|     await testSSOAuthOption('oidc'); | ||||
| }); | ||||
| 
 | ||||
| test('should render SAML auth', async () => { | ||||
|     await testSSOAuthOption('saml'); | ||||
| }); | ||||
| 
 | ||||
| const testSSOAuthOption = async (authOption: string) => { | ||||
|     const path = `/auth/${authOption}/login`; | ||||
|     const testId = `${SSO_LOGIN_BUTTON}-${authOption}`; | ||||
| 
 | ||||
|     testServerRoute(server, '*', { | ||||
|         defaultHidden: true, | ||||
|         message: 'You must sign in in order to use Unleash', | ||||
|         options: [{ type: authOption, message: '...', path: path }], | ||||
|         path: '/auth/simple/login', | ||||
|         type: 'password', | ||||
|     }); | ||||
| 
 | ||||
|     render( | ||||
|         <TestContext> | ||||
|             <Authentication redirect="/" /> | ||||
|         </TestContext> | ||||
|     ); | ||||
| 
 | ||||
|     const ssoLink = await screen.findByTestId(testId); | ||||
|     expect(ssoLink.getAttribute('href')).toEqual(path); | ||||
|     expect(screen.queryByTestId(LOGIN_EMAIL_ID)).not.toBeInTheDocument(); | ||||
|     expect(screen.queryByTestId(LOGIN_PASSWORD_ID)).not.toBeInTheDocument(); | ||||
|     expect(screen.queryByTestId(LOGIN_BUTTON)).not.toBeInTheDocument(); | ||||
| }; | ||||
| @ -14,16 +14,20 @@ import useQueryParams from 'hooks/useQueryParams'; | ||||
| import ConditionallyRender from 'component/common/ConditionallyRender'; | ||||
| import { Alert } from '@material-ui/lab'; | ||||
| import { useAuthDetails } from 'hooks/api/getters/useAuth/useAuthDetails'; | ||||
| import { AUTH_PAGE_ID } from 'utils/testIds'; | ||||
| 
 | ||||
| interface IAuthenticationProps { | ||||
|     redirect: string; | ||||
| } | ||||
| 
 | ||||
| const Authentication = ({ redirect }: IAuthenticationProps) => { | ||||
|     const { authDetails } = useAuthDetails(); | ||||
|     const params = useQueryParams(); | ||||
| 
 | ||||
|     const error = params.get('errorMsg'); | ||||
|     if (!authDetails) return null; | ||||
| 
 | ||||
|     if (!authDetails) { | ||||
|         return null; | ||||
|     } | ||||
| 
 | ||||
|     let content; | ||||
|     if (authDetails.type === PASSWORD_TYPE) { | ||||
| @ -53,9 +57,10 @@ const Authentication = ({ redirect }: IAuthenticationProps) => { | ||||
|     } else { | ||||
|         content = <AuthenticationCustomComponent authDetails={authDetails} />; | ||||
|     } | ||||
| 
 | ||||
|     return ( | ||||
|         <> | ||||
|             <div style={{ maxWidth: '350px' }}> | ||||
|             <div style={{ maxWidth: '350px' }} data-testid={AUTH_PAGE_ID}> | ||||
|                 <ConditionallyRender | ||||
|                     condition={Boolean(error)} | ||||
|                     show={<Alert severity="error">{error}</Alert>} | ||||
|  | ||||
| @ -45,12 +45,12 @@ const DemoAuth = ({ authDetails, redirect }) => { | ||||
|                         value={email} | ||||
|                         className={styles.emailField} | ||||
|                         onChange={handleChange} | ||||
|                         inputProps={{ 'data-test': 'email-input-field' }} | ||||
|                         inputProps={{ 'data-testid': 'email-input-field' }} | ||||
|                         size="small" | ||||
|                         variant="outlined" | ||||
|                         label="Email" | ||||
|                         name="email" | ||||
|                         data-test={LOGIN_EMAIL_ID} | ||||
|                         data-testid={LOGIN_EMAIL_ID} | ||||
|                         required | ||||
|                         type="email" | ||||
|                     /> | ||||
| @ -60,7 +60,7 @@ const DemoAuth = ({ authDetails, redirect }) => { | ||||
|                         variant="contained" | ||||
|                         color="primary" | ||||
|                         className={styles.button} | ||||
|                         data-test={LOGIN_BUTTON} | ||||
|                         data-testid={LOGIN_BUTTON} | ||||
|                     > | ||||
|                         Sign in | ||||
|                     </Button> | ||||
|  | ||||
| @ -0,0 +1,15 @@ | ||||
| import { render, screen } from '@testing-library/react'; | ||||
| import { FORGOTTEN_PASSWORD_FIELD } from 'utils/testIds'; | ||||
| import React from 'react'; | ||||
| import { TestContext } from 'utils/testContext'; | ||||
| import ForgottenPassword from 'component/user/ForgottenPassword/ForgottenPassword'; | ||||
| 
 | ||||
| test('should render password auth', async () => { | ||||
|     render( | ||||
|         <TestContext> | ||||
|             <ForgottenPassword /> | ||||
|         </TestContext> | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByTestId(FORGOTTEN_PASSWORD_FIELD); | ||||
| }); | ||||
| @ -96,7 +96,7 @@ const ForgottenPassword = () => { | ||||
|                         placeholder="email" | ||||
|                         type="email" | ||||
|                         data-loading | ||||
|                         data-test={FORGOTTEN_PASSWORD_FIELD} | ||||
|                         data-testid={FORGOTTEN_PASSWORD_FIELD} | ||||
|                         value={email} | ||||
|                         onChange={e => { | ||||
|                             setEmail(e.target.value); | ||||
|  | ||||
| @ -109,7 +109,7 @@ const HostedAuth = ({ authDetails, redirect }) => { | ||||
|                                 helperText={usernameError} | ||||
|                                 variant="outlined" | ||||
|                                 size="small" | ||||
|                                 data-test={LOGIN_EMAIL_ID} | ||||
|                                 data-testid={LOGIN_EMAIL_ID} | ||||
|                             /> | ||||
|                             <PasswordField | ||||
|                                 label="Password" | ||||
| @ -118,7 +118,7 @@ const HostedAuth = ({ authDetails, redirect }) => { | ||||
|                                 value={password} | ||||
|                                 error={!!passwordError} | ||||
|                                 helperText={passwordError} | ||||
|                                 data-test={LOGIN_PASSWORD_ID} | ||||
|                                 data-testid={LOGIN_PASSWORD_ID} | ||||
|                             /> | ||||
|                             <Grid container> | ||||
|                                 <Button | ||||
| @ -126,7 +126,7 @@ const HostedAuth = ({ authDetails, redirect }) => { | ||||
|                                     color="primary" | ||||
|                                     type="submit" | ||||
|                                     className={styles.button} | ||||
|                                     data-test={LOGIN_BUTTON} | ||||
|                                     data-testid={LOGIN_BUTTON} | ||||
|                                 > | ||||
|                                     Sign in | ||||
|                                 </Button> | ||||
|  | ||||
| @ -108,7 +108,7 @@ const PasswordAuth = ({ authDetails, redirect }) => { | ||||
|                                 error={!!usernameError} | ||||
|                                 helperText={usernameError} | ||||
|                                 autoComplete="true" | ||||
|                                 data-test={LOGIN_EMAIL_ID} | ||||
|                                 data-testid={LOGIN_EMAIL_ID} | ||||
|                                 variant="outlined" | ||||
|                                 size="small" | ||||
|                             /> | ||||
| @ -120,14 +120,14 @@ const PasswordAuth = ({ authDetails, redirect }) => { | ||||
|                                 error={!!passwordError} | ||||
|                                 helperText={passwordError} | ||||
|                                 autoComplete="true" | ||||
|                                 data-test={LOGIN_PASSWORD_ID} | ||||
|                                 data-testid={LOGIN_PASSWORD_ID} | ||||
|                             /> | ||||
|                             <Button | ||||
|                                 variant="contained" | ||||
|                                 color="primary" | ||||
|                                 type="submit" | ||||
|                                 style={{ width: '150px', margin: '1rem auto' }} | ||||
|                                 data-test={LOGIN_BUTTON} | ||||
|                                 data-testid={LOGIN_BUTTON} | ||||
|                             > | ||||
|                                 Sign in | ||||
|                             </Button> | ||||
|  | ||||
| @ -0,0 +1,26 @@ | ||||
| import { render, screen } from '@testing-library/react'; | ||||
| import { INVALID_TOKEN_BUTTON } from 'utils/testIds'; | ||||
| import React from 'react'; | ||||
| import { TestContext } from 'utils/testContext'; | ||||
| import ResetPassword from 'component/user/ResetPassword/ResetPassword'; | ||||
| import { MemoryRouter } from 'react-router-dom'; | ||||
| import { INVALID_TOKEN_ERROR } from 'hooks/api/getters/useResetPassword/useResetPassword'; | ||||
| import { testServerSetup, testServerRoute } from 'utils/testServer'; | ||||
| 
 | ||||
| const server = testServerSetup(); | ||||
| 
 | ||||
| test('should render password auth', async () => { | ||||
|     testServerRoute(server, '/auth/reset/validate', { | ||||
|         name: INVALID_TOKEN_ERROR, | ||||
|     }); | ||||
| 
 | ||||
|     render( | ||||
|         <TestContext> | ||||
|             <MemoryRouter initialEntries={['/new-user?token=invalid']}> | ||||
|                 <ResetPassword /> | ||||
|             </MemoryRouter> | ||||
|         </TestContext> | ||||
|     ); | ||||
| 
 | ||||
|     await screen.findByTestId(INVALID_TOKEN_BUTTON); | ||||
| }); | ||||
| @ -51,14 +51,14 @@ const SimpleAuth = ({ authDetails, redirect }) => { | ||||
|                 <TextField | ||||
|                     value={email} | ||||
|                     onChange={handleChange} | ||||
|                     inputProps={{ 'data-test': 'email-input-field' }} | ||||
|                     inputProps={{ 'data-testid': 'email-input-field' }} | ||||
|                     size="small" | ||||
|                     variant="outlined" | ||||
|                     label="Email" | ||||
|                     name="email" | ||||
|                     required | ||||
|                     type="email" | ||||
|                     data-test={LOGIN_EMAIL_ID} | ||||
|                     data-testid={LOGIN_EMAIL_ID} | ||||
|                 /> | ||||
|                 <br /> | ||||
| 
 | ||||
| @ -68,7 +68,7 @@ const SimpleAuth = ({ authDetails, redirect }) => { | ||||
|                         variant="contained" | ||||
|                         color="primary" | ||||
|                         className={styles.button} | ||||
|                         data-test={LOGIN_BUTTON} | ||||
|                         data-testid={LOGIN_BUTTON} | ||||
|                     > | ||||
|                         Sign in | ||||
|                     </Button> | ||||
|  | ||||
| @ -71,7 +71,7 @@ const UserProfile = ({ | ||||
|                     <Avatar | ||||
|                         alt="user image" | ||||
|                         src={imageUrl} | ||||
|                         data-test={HEADER_USER_AVATAR} | ||||
|                         data-testid={HEADER_USER_AVATAR} | ||||
|                     /> | ||||
|                     <KeyboardArrowDownIcon /> | ||||
|                 </Button> | ||||
|  | ||||
| @ -29,7 +29,7 @@ const AuthOptions = ({ options }: IAuthOptionProps) => { | ||||
|                         variant="outlined" | ||||
|                         href={o.path} | ||||
|                         size="small" | ||||
|                         data-test={`${SSO_LOGIN_BUTTON}-${o.type}`} | ||||
|                         data-testid={`${SSO_LOGIN_BUTTON}-${o.type}`} | ||||
|                         style={{ height: '40px', color: '#000' }} | ||||
|                         startIcon={ | ||||
|                             <ConditionallyRender | ||||
|  | ||||
| @ -27,7 +27,7 @@ const InvalidToken = () => { | ||||
|                 color="primary" | ||||
|                 component={Link} | ||||
|                 to="forgotten-password" | ||||
|                 data-test={INVALID_TOKEN_BUTTON} | ||||
|                 data-testid={INVALID_TOKEN_BUTTON} | ||||
|             > | ||||
|                 Reset password | ||||
|             </Button> | ||||
|  | ||||
| @ -11,7 +11,7 @@ const getFetcher = (token: string) => () => { | ||||
|     }).then(res => res.json()); | ||||
| }; | ||||
| 
 | ||||
| const INVALID_TOKEN_ERROR = 'InvalidTokenError'; | ||||
| export const INVALID_TOKEN_ERROR = 'InvalidTokenError'; | ||||
| const USED_TOKEN_ERROR = 'UsedTokenError'; | ||||
| 
 | ||||
| const useResetPassword = (options: SWRConfiguration = {}) => { | ||||
|  | ||||
							
								
								
									
										15
									
								
								frontend/src/utils/testContext.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								frontend/src/utils/testContext.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import { SWRConfig } from 'swr'; | ||||
| import { MemoryRouter } from 'react-router-dom'; | ||||
| import { ThemeProvider } from '@material-ui/core/styles'; | ||||
| import theme from 'themes/mainTheme'; | ||||
| import React from 'react'; | ||||
| 
 | ||||
| export const TestContext: React.FC = ({ children }) => { | ||||
|     return ( | ||||
|         <SWRConfig value={{ provider: () => new Map() }}> | ||||
|             <MemoryRouter> | ||||
|                 <ThemeProvider theme={theme}>{children}</ThemeProvider> | ||||
|             </MemoryRouter> | ||||
|         </SWRConfig> | ||||
|     ); | ||||
| }; | ||||
| @ -48,3 +48,4 @@ export const CLOSE_SPLASH = 'CLOSE_SPLASH'; | ||||
| export const INPUT_ERROR_TEXT = 'INPUT_ERROR_TEXT'; | ||||
| export const HEADER_USER_AVATAR = 'HEADER_USER_AVATAR'; | ||||
| export const SIDEBAR_MODAL_ID = 'SIDEBAR_MODAL_ID'; | ||||
| export const AUTH_PAGE_ID = 'AUTH_PAGE_ID'; | ||||
|  | ||||
							
								
								
									
										24
									
								
								frontend/src/utils/testServer.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								frontend/src/utils/testServer.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| import { SetupServerApi, setupServer } from 'msw/node'; | ||||
| import { rest } from 'msw'; | ||||
| 
 | ||||
| export const testServerSetup = (): SetupServerApi => { | ||||
|     const server = setupServer(); | ||||
| 
 | ||||
|     beforeAll(() => server.listen()); | ||||
|     afterAll(() => server.close()); | ||||
|     afterEach(() => server.resetHandlers()); | ||||
| 
 | ||||
|     return server; | ||||
| }; | ||||
| 
 | ||||
| export const testServerRoute = ( | ||||
|     server: SetupServerApi, | ||||
|     path: string, | ||||
|     json: object | ||||
| ) => { | ||||
|     server.use( | ||||
|         rest.get(path, (req, res, ctx) => { | ||||
|             return res(ctx.json(json)); | ||||
|         }) | ||||
|     ); | ||||
| }; | ||||
| @ -1482,6 +1482,26 @@ | ||||
|     prop-types "^15.7.2" | ||||
|     react-is "^16.8.0 || ^17.0.0" | ||||
| 
 | ||||
| "@mswjs/cookies@^0.2.0": | ||||
|   version "0.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/@mswjs/cookies/-/cookies-0.2.0.tgz#7ef2b5d7e444498bb27cf57720e61f76a4ce9f23" | ||||
|   integrity sha512-GTKYnIfXVP8GL8HRWrse+ujqDXCLKvu7+JoL6pvZFzS/d2i9pziByoWD69cOe35JNoSrx2DPNqrhUF+vgV3qUA== | ||||
|   dependencies: | ||||
|     "@types/set-cookie-parser" "^2.4.0" | ||||
|     set-cookie-parser "^2.4.6" | ||||
| 
 | ||||
| "@mswjs/interceptors@^0.15.1": | ||||
|   version "0.15.1" | ||||
|   resolved "https://registry.yarnpkg.com/@mswjs/interceptors/-/interceptors-0.15.1.tgz#4a0009f56e51bc2cd3176f1507065c7d2f6c0d5e" | ||||
|   integrity sha512-D5B+ZJNlfvBm6ZctAfRBdNJdCHYAe2Ix4My5qfbHV5WH+3lkt3mmsjiWJzEh5ZwGDauzY487TldI275If7DJVw== | ||||
|   dependencies: | ||||
|     "@open-draft/until" "^1.0.3" | ||||
|     "@xmldom/xmldom" "^0.7.5" | ||||
|     debug "^4.3.3" | ||||
|     headers-polyfill "^3.0.4" | ||||
|     outvariant "^1.2.1" | ||||
|     strict-event-emitter "^0.2.0" | ||||
| 
 | ||||
| "@nodelib/fs.scandir@2.1.5": | ||||
|   version "2.1.5" | ||||
|   resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" | ||||
| @ -1503,6 +1523,11 @@ | ||||
|     "@nodelib/fs.scandir" "2.1.5" | ||||
|     fastq "^1.6.0" | ||||
| 
 | ||||
| "@open-draft/until@^1.0.3": | ||||
|   version "1.0.3" | ||||
|   resolved "https://registry.yarnpkg.com/@open-draft/until/-/until-1.0.3.tgz#db9cc719191a62e7d9200f6e7bab21c5b848adca" | ||||
|   integrity sha512-Aq58f5HiWdyDlFffbbSjAlv596h/cOnt2DO1w3DOC7OJ5EHs0hd/nycJfiu9RJbT6Yk6F1knnRRXNSpxoIVZ9Q== | ||||
| 
 | ||||
| "@pmmmwh/react-refresh-webpack-plugin@^0.5.3": | ||||
|   version "0.5.5" | ||||
|   resolved "https://registry.yarnpkg.com/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.5.tgz#e77aac783bd079f548daa0a7f080ab5b5a9741ca" | ||||
| @ -1848,6 +1873,11 @@ | ||||
|   dependencies: | ||||
|     "@types/node" "*" | ||||
| 
 | ||||
| "@types/cookie@^0.4.1": | ||||
|   version "0.4.1" | ||||
|   resolved "https://registry.yarnpkg.com/@types/cookie/-/cookie-0.4.1.tgz#bfd02c1f2224567676c1545199f87c3a861d878d" | ||||
|   integrity sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q== | ||||
| 
 | ||||
| "@types/debounce@1.2.1": | ||||
|   version "1.2.1" | ||||
|   resolved "https://registry.yarnpkg.com/@types/debounce/-/debounce-1.2.1.tgz#79b65710bc8b6d44094d286aecf38e44f9627852" | ||||
| @ -1962,6 +1992,11 @@ | ||||
|     jest-matcher-utils "^27.0.0" | ||||
|     pretty-format "^27.0.0" | ||||
| 
 | ||||
| "@types/js-levenshtein@^1.1.1": | ||||
|   version "1.1.1" | ||||
|   resolved "https://registry.yarnpkg.com/@types/js-levenshtein/-/js-levenshtein-1.1.1.tgz#ba05426a43f9e4e30b631941e0aa17bf0c890ed5" | ||||
|   integrity sha512-qC4bCqYGy1y/NP7dDVr7KJarn+PbX1nSpwA7JXdu0HxT3QYjO8MJ+cntENtHFVy2dRAyBV23OZ6MxsW1AM1L8g== | ||||
| 
 | ||||
| "@types/json-schema@*", "@types/json-schema@^7.0.4", "@types/json-schema@^7.0.5", "@types/json-schema@^7.0.8", "@types/json-schema@^7.0.9": | ||||
|   version "7.0.11" | ||||
|   resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.11.tgz#d421b6c527a3037f7c84433fd2c4229e016863d3" | ||||
| @ -2141,6 +2176,13 @@ | ||||
|     "@types/mime" "^1" | ||||
|     "@types/node" "*" | ||||
| 
 | ||||
| "@types/set-cookie-parser@^2.4.0": | ||||
|   version "2.4.2" | ||||
|   resolved "https://registry.yarnpkg.com/@types/set-cookie-parser/-/set-cookie-parser-2.4.2.tgz#b6a955219b54151bfebd4521170723df5e13caad" | ||||
|   integrity sha512-fBZgytwhYAUkj/jC/FAV4RQ5EerRup1YQsXQCh8rZfiHkc4UahC192oH0smGwsXol3cL3A5oETuAHeQHmhXM4w== | ||||
|   dependencies: | ||||
|     "@types/node" "*" | ||||
| 
 | ||||
| "@types/sinonjs__fake-timers@8.1.1": | ||||
|   version "8.1.1" | ||||
|   resolved "https://registry.yarnpkg.com/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz#b49c2c70150141a15e0fa7e79cf1f92a72934ce3" | ||||
| @ -2409,6 +2451,11 @@ | ||||
|     "@webassemblyjs/ast" "1.11.1" | ||||
|     "@xtuc/long" "4.2.2" | ||||
| 
 | ||||
| "@xmldom/xmldom@^0.7.5": | ||||
|   version "0.7.5" | ||||
|   resolved "https://registry.yarnpkg.com/@xmldom/xmldom/-/xmldom-0.7.5.tgz#09fa51e356d07d0be200642b0e4f91d8e6dd408d" | ||||
|   integrity sha512-V3BIhmY36fXZ1OtVcI9W+FxQqxVLsPKcNjWigIaa81dLC9IolJl5Mt4Cvhmr0flUnjSpTdrbMTSbXqYqV5dT6A== | ||||
| 
 | ||||
| "@xtuc/ieee754@^1.2.0": | ||||
|   version "1.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/@xtuc/ieee754/-/ieee754-1.2.0.tgz#eef014a3145ae477a1cbc00cd1e552336dceb790" | ||||
| @ -2950,6 +2997,15 @@ binary-extensions@^2.0.0: | ||||
|   resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.2.0.tgz#75f502eeaf9ffde42fc98829645be4ea76bd9e2d" | ||||
|   integrity sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA== | ||||
| 
 | ||||
| bl@^4.1.0: | ||||
|   version "4.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/bl/-/bl-4.1.0.tgz#451535264182bec2fbbc83a62ab98cf11d9f7b3a" | ||||
|   integrity sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w== | ||||
|   dependencies: | ||||
|     buffer "^5.5.0" | ||||
|     inherits "^2.0.4" | ||||
|     readable-stream "^3.4.0" | ||||
| 
 | ||||
| blob-util@^2.0.2: | ||||
|   version "2.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/blob-util/-/blob-util-2.0.2.tgz#3b4e3c281111bb7f11128518006cdc60b403a1eb" | ||||
| @ -3039,7 +3095,7 @@ buffer-from@^1.0.0: | ||||
|   resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" | ||||
|   integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== | ||||
| 
 | ||||
| buffer@^5.6.0: | ||||
| buffer@^5.5.0, buffer@^5.6.0: | ||||
|   version "5.7.1" | ||||
|   resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" | ||||
|   integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== | ||||
| @ -3128,6 +3184,14 @@ caseless@~0.12.0: | ||||
|   resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" | ||||
|   integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= | ||||
| 
 | ||||
| chalk@4.1.1: | ||||
|   version "4.1.1" | ||||
|   resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad" | ||||
|   integrity sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg== | ||||
|   dependencies: | ||||
|     ansi-styles "^4.1.0" | ||||
|     supports-color "^7.1.0" | ||||
| 
 | ||||
| chalk@^2.0.0, chalk@^2.4.1: | ||||
|   version "2.4.2" | ||||
|   resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" | ||||
| @ -3145,7 +3209,7 @@ chalk@^3.0.0: | ||||
|     ansi-styles "^4.1.0" | ||||
|     supports-color "^7.1.0" | ||||
| 
 | ||||
| chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.2: | ||||
| chalk@^4.0.0, chalk@^4.0.2, chalk@^4.1.0, chalk@^4.1.1, chalk@^4.1.2: | ||||
|   version "4.1.2" | ||||
|   resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" | ||||
|   integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== | ||||
| @ -3168,6 +3232,11 @@ charcodes@^0.2.0: | ||||
|   resolved "https://registry.yarnpkg.com/charcodes/-/charcodes-0.2.0.tgz#5208d327e6cc05f99eb80ffc814707572d1f14e4" | ||||
|   integrity sha512-Y4kiDb+AM4Ecy58YkuZrrSRJBDQdQ2L+NyS1vHHFtNtUjgutcZfx3yp1dAONI/oPaPmyGfCLx5CxL+zauIMyKQ== | ||||
| 
 | ||||
| chardet@^0.7.0: | ||||
|   version "0.7.0" | ||||
|   resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" | ||||
|   integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== | ||||
| 
 | ||||
| chart.js@3.7.1: | ||||
|   version "3.7.1" | ||||
|   resolved "https://registry.yarnpkg.com/chart.js/-/chart.js-3.7.1.tgz#0516f690c6a8680c6c707e31a4c1807a6f400ada" | ||||
| @ -3242,6 +3311,11 @@ cli-cursor@^3.1.0: | ||||
|   dependencies: | ||||
|     restore-cursor "^3.1.0" | ||||
| 
 | ||||
| cli-spinners@^2.5.0: | ||||
|   version "2.6.1" | ||||
|   resolved "https://registry.yarnpkg.com/cli-spinners/-/cli-spinners-2.6.1.tgz#adc954ebe281c37a6319bfa401e6dd2488ffb70d" | ||||
|   integrity sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g== | ||||
| 
 | ||||
| cli-table3@~0.6.1: | ||||
|   version "0.6.1" | ||||
|   resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.6.1.tgz#36ce9b7af4847f288d3cdd081fbd09bf7bd237b8" | ||||
| @ -3259,6 +3333,11 @@ cli-truncate@^2.1.0: | ||||
|     slice-ansi "^3.0.0" | ||||
|     string-width "^4.2.0" | ||||
| 
 | ||||
| cli-width@^3.0.0: | ||||
|   version "3.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-3.0.0.tgz#a2f48437a2caa9a22436e794bf071ec9e61cedf6" | ||||
|   integrity sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw== | ||||
| 
 | ||||
| cliui@^7.0.2: | ||||
|   version "7.0.4" | ||||
|   resolved "https://registry.yarnpkg.com/cliui/-/cliui-7.0.4.tgz#a0265ee655476fc807aea9df3df8df7783808b4f" | ||||
| @ -3268,6 +3347,11 @@ cliui@^7.0.2: | ||||
|     strip-ansi "^6.0.0" | ||||
|     wrap-ansi "^7.0.0" | ||||
| 
 | ||||
| clone@^1.0.2: | ||||
|   version "1.0.4" | ||||
|   resolved "https://registry.yarnpkg.com/clone/-/clone-1.0.4.tgz#da309cc263df15994c688ca902179ca3c7cd7c7e" | ||||
|   integrity sha1-2jCcwmPfFZlMaIypAheco8fNfH4= | ||||
| 
 | ||||
| clsx@^1.0.4: | ||||
|   version "1.1.1" | ||||
|   resolved "https://registry.yarnpkg.com/clsx/-/clsx-1.1.1.tgz#98b3134f9abbdf23b2663491ace13c5c03a73188" | ||||
| @ -3432,7 +3516,7 @@ cookie-signature@1.0.6: | ||||
|   resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" | ||||
|   integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= | ||||
| 
 | ||||
| cookie@0.4.2: | ||||
| cookie@0.4.2, cookie@^0.4.2: | ||||
|   version "0.4.2" | ||||
|   resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.4.2.tgz#0e41f24de5ecf317947c82fc789e06a884824432" | ||||
|   integrity sha512-aSWTXFzaKWkvHO1Ny/s+ePFpvKsPnjc551iI41v3ny/ow6tBG5Vd+FuqGNhh1LxOmVzOlGUriIlOaokOvhaStA== | ||||
| @ -3816,7 +3900,7 @@ debug@2.6.9, debug@^2.6.0, debug@^2.6.9: | ||||
|   dependencies: | ||||
|     ms "2.0.0" | ||||
| 
 | ||||
| debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2: | ||||
| debug@4, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3: | ||||
|   version "4.3.4" | ||||
|   resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" | ||||
|   integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== | ||||
| @ -3867,6 +3951,13 @@ default-gateway@^6.0.3: | ||||
|   dependencies: | ||||
|     execa "^5.0.0" | ||||
| 
 | ||||
| defaults@^1.0.3: | ||||
|   version "1.0.3" | ||||
|   resolved "https://registry.yarnpkg.com/defaults/-/defaults-1.0.3.tgz#c656051e9817d9ff08ed881477f3fe4019f3ef7d" | ||||
|   integrity sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= | ||||
|   dependencies: | ||||
|     clone "^1.0.2" | ||||
| 
 | ||||
| define-lazy-prop@^2.0.0: | ||||
|   version "2.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" | ||||
| @ -4520,7 +4611,7 @@ eventemitter3@^4.0.0: | ||||
|   resolved "https://registry.yarnpkg.com/eventemitter3/-/eventemitter3-4.0.7.tgz#2de9b68f6528d5644ef5c59526a1b4a07306169f" | ||||
|   integrity sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw== | ||||
| 
 | ||||
| events@^3.2.0: | ||||
| events@^3.2.0, events@^3.3.0: | ||||
|   version "3.3.0" | ||||
|   resolved "https://registry.yarnpkg.com/events/-/events-3.3.0.tgz#31a95ad0a924e2d2c419a813aeb2c4e878ea7400" | ||||
|   integrity sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q== | ||||
| @ -4618,6 +4709,15 @@ extend@~3.0.2: | ||||
|   resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" | ||||
|   integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== | ||||
| 
 | ||||
| external-editor@^3.0.3: | ||||
|   version "3.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" | ||||
|   integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== | ||||
|   dependencies: | ||||
|     chardet "^0.7.0" | ||||
|     iconv-lite "^0.4.24" | ||||
|     tmp "^0.0.33" | ||||
| 
 | ||||
| extract-zip@2.0.1: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/extract-zip/-/extract-zip-2.0.1.tgz#663dca56fe46df890d5f131ef4a06d22bb8ba13a" | ||||
| @ -4698,7 +4798,7 @@ fd-slicer@~1.1.0: | ||||
|   dependencies: | ||||
|     pend "~1.2.0" | ||||
| 
 | ||||
| figures@^3.2.0: | ||||
| figures@^3.0.0, figures@^3.2.0: | ||||
|   version "3.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/figures/-/figures-3.2.0.tgz#625c18bd293c604dc4a8ddb2febf0c88341746af" | ||||
|   integrity sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg== | ||||
| @ -5056,6 +5156,11 @@ graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.2.0, graceful-fs@^4.2.4, | ||||
|   resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" | ||||
|   integrity sha512-9ByhssR2fPVsNZj478qUUbKfmL0+t5BDVyjShtyZZLiK7ZDAArFFfopyOTj0M05wE2tJPisA4iTnnXl2YoPvOA== | ||||
| 
 | ||||
| graphql@^16.3.0: | ||||
|   version "16.3.0" | ||||
|   resolved "https://registry.yarnpkg.com/graphql/-/graphql-16.3.0.tgz#a91e24d10babf9e60c706919bb182b53ccdffc05" | ||||
|   integrity sha512-xm+ANmA16BzCT5pLjuXySbQVFwH3oJctUVdy81w1sV0vBU0KgDdBGtxQOUd5zqOBk/JayAFeG8Dlmeq74rjm/A== | ||||
| 
 | ||||
| gzip-size@^6.0.0: | ||||
|   version "6.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" | ||||
| @ -5112,6 +5217,11 @@ he@^1.2.0: | ||||
|   resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" | ||||
|   integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== | ||||
| 
 | ||||
| headers-polyfill@^3.0.4: | ||||
|   version "3.0.7" | ||||
|   resolved "https://registry.yarnpkg.com/headers-polyfill/-/headers-polyfill-3.0.7.tgz#725c4f591e6748f46b036197eae102c92b959ff4" | ||||
|   integrity sha512-JoLCAdCEab58+2/yEmSnOlficyHFpIl0XJqwu3l+Unkm1gXpFUYsThz6Yha3D6tNhocWkCPfyW0YVIGWFqTi7w== | ||||
| 
 | ||||
| history@^4.9.0: | ||||
|   version "4.10.1" | ||||
|   resolved "https://registry.yarnpkg.com/history/-/history-4.10.1.tgz#33371a65e3a83b267434e2b3f3b1b4c58aad4cf3" | ||||
| @ -5289,7 +5399,7 @@ hyphenate-style-name@^1.0.3: | ||||
|   resolved "https://registry.yarnpkg.com/hyphenate-style-name/-/hyphenate-style-name-1.0.4.tgz#691879af8e220aea5750e8827db4ef62a54e361d" | ||||
|   integrity sha512-ygGZLjmXfPHj+ZWh6LwbC37l43MhfztxetbFCoYTM2VjkIUpeHgSNn7QIyVFj7YQ1Wl9Cbw5sholVJPzWvC2MQ== | ||||
| 
 | ||||
| iconv-lite@0.4.24: | ||||
| iconv-lite@0.4.24, iconv-lite@^0.4.24: | ||||
|   version "0.4.24" | ||||
|   resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" | ||||
|   integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== | ||||
| @ -5394,6 +5504,26 @@ ini@^1.3.5: | ||||
|   resolved "https://registry.yarnpkg.com/ini/-/ini-1.3.8.tgz#a29da425b48806f34767a4efce397269af28432c" | ||||
|   integrity sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew== | ||||
| 
 | ||||
| inquirer@^8.2.0: | ||||
|   version "8.2.2" | ||||
|   resolved "https://registry.yarnpkg.com/inquirer/-/inquirer-8.2.2.tgz#1310517a87a0814d25336c78a20b44c3d9b7629d" | ||||
|   integrity sha512-pG7I/si6K/0X7p1qU+rfWnpTE1UIkTONN1wxtzh0d+dHXtT/JG6qBgLxoyHVsQa8cFABxAPh0pD6uUUHiAoaow== | ||||
|   dependencies: | ||||
|     ansi-escapes "^4.2.1" | ||||
|     chalk "^4.1.1" | ||||
|     cli-cursor "^3.1.0" | ||||
|     cli-width "^3.0.0" | ||||
|     external-editor "^3.0.3" | ||||
|     figures "^3.0.0" | ||||
|     lodash "^4.17.21" | ||||
|     mute-stream "0.0.8" | ||||
|     ora "^5.4.1" | ||||
|     run-async "^2.4.0" | ||||
|     rxjs "^7.5.5" | ||||
|     string-width "^4.1.0" | ||||
|     strip-ansi "^6.0.0" | ||||
|     through "^2.3.6" | ||||
| 
 | ||||
| internal-slot@^1.0.3: | ||||
|   version "1.0.3" | ||||
|   resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.3.tgz#7347e307deeea2faac2ac6205d4bc7d34967f59c" | ||||
| @ -5506,6 +5636,11 @@ is-installed-globally@~0.4.0: | ||||
|     global-dirs "^3.0.0" | ||||
|     is-path-inside "^3.0.2" | ||||
| 
 | ||||
| is-interactive@^1.0.0: | ||||
|   version "1.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/is-interactive/-/is-interactive-1.0.0.tgz#cea6e6ae5c870a7b0a0004070b7b587e0252912e" | ||||
|   integrity sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w== | ||||
| 
 | ||||
| is-module@^1.0.0: | ||||
|   version "1.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/is-module/-/is-module-1.0.0.tgz#3258fb69f78c14d5b815d664336b4cffb6441591" | ||||
| @ -5516,6 +5651,11 @@ is-negative-zero@^2.0.2: | ||||
|   resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" | ||||
|   integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== | ||||
| 
 | ||||
| is-node-process@^1.0.1: | ||||
|   version "1.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/is-node-process/-/is-node-process-1.0.1.tgz#4fc7ac3a91e8aac58175fe0578abbc56f2831b23" | ||||
|   integrity sha512-5IcdXuf++TTNt3oGl9EBdkvndXA8gmc4bz/Y+mdEpWh3Mcn/+kOw6hI7LD5CocqJWMzeb0I0ClndRVNdEPuJXQ== | ||||
| 
 | ||||
| is-number-object@^1.0.4: | ||||
|   version "1.0.7" | ||||
|   resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" | ||||
| @ -6115,6 +6255,11 @@ jest@^27.4.3: | ||||
|     import-local "^3.0.2" | ||||
|     jest-cli "^27.5.1" | ||||
| 
 | ||||
| js-levenshtein@^1.1.6: | ||||
|   version "1.1.6" | ||||
|   resolved "https://registry.yarnpkg.com/js-levenshtein/-/js-levenshtein-1.1.6.tgz#c6cee58eb3550372df8deb85fad5ce66ce01d59d" | ||||
|   integrity sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g== | ||||
| 
 | ||||
| "js-tokens@^3.0.0 || ^4.0.0", js-tokens@^4.0.0: | ||||
|   version "4.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" | ||||
| @ -6498,7 +6643,7 @@ lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.7. | ||||
|   resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" | ||||
|   integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== | ||||
| 
 | ||||
| log-symbols@^4.0.0: | ||||
| log-symbols@^4.0.0, log-symbols@^4.1.0: | ||||
|   version "4.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" | ||||
|   integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== | ||||
| @ -6535,11 +6680,6 @@ lru-cache@^7.4.0: | ||||
|   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.7.3.tgz#98cd19eef89ce6a4a3c4502c17c833888677c252" | ||||
|   integrity sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw== | ||||
| 
 | ||||
| lru-cache@^7.4.0: | ||||
|   version "7.7.3" | ||||
|   resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.7.3.tgz#98cd19eef89ce6a4a3c4502c17c833888677c252" | ||||
|   integrity sha512-WY9wjJNQt9+PZilnLbuFKM+SwDull9+6IAguOrarOMoOHTcJ9GnXSO11+Gw6c7xtDkBkthR57OZMtZKYr+1CEw== | ||||
| 
 | ||||
| lz-string@^1.4.4: | ||||
|   version "1.4.4" | ||||
|   resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" | ||||
| @ -6704,6 +6844,31 @@ ms@2.1.3, ms@^2.1.1: | ||||
|   resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" | ||||
|   integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== | ||||
| 
 | ||||
| msw@^0.39.2: | ||||
|   version "0.39.2" | ||||
|   resolved "https://registry.yarnpkg.com/msw/-/msw-0.39.2.tgz#832e9274db62c43cb79854d5a69dce031c700de8" | ||||
|   integrity sha512-ju/HpqQpE4/qCxZ23t5Gaau0KREn4QuFzdG28nP1EpidMrymMJuIvNd32+2uGTGG031PMwrC41YW7vCxHOwyHA== | ||||
|   dependencies: | ||||
|     "@mswjs/cookies" "^0.2.0" | ||||
|     "@mswjs/interceptors" "^0.15.1" | ||||
|     "@open-draft/until" "^1.0.3" | ||||
|     "@types/cookie" "^0.4.1" | ||||
|     "@types/js-levenshtein" "^1.1.1" | ||||
|     chalk "4.1.1" | ||||
|     chokidar "^3.4.2" | ||||
|     cookie "^0.4.2" | ||||
|     graphql "^16.3.0" | ||||
|     headers-polyfill "^3.0.4" | ||||
|     inquirer "^8.2.0" | ||||
|     is-node-process "^1.0.1" | ||||
|     js-levenshtein "^1.1.6" | ||||
|     node-fetch "^2.6.7" | ||||
|     path-to-regexp "^6.2.0" | ||||
|     statuses "^2.0.0" | ||||
|     strict-event-emitter "^0.2.0" | ||||
|     type-fest "^1.2.2" | ||||
|     yargs "^17.3.1" | ||||
| 
 | ||||
| multicast-dns@^7.2.4: | ||||
|   version "7.2.4" | ||||
|   resolved "https://registry.yarnpkg.com/multicast-dns/-/multicast-dns-7.2.4.tgz#cf0b115c31e922aeb20b64e6556cbeb34cf0dd19" | ||||
| @ -6712,6 +6877,11 @@ multicast-dns@^7.2.4: | ||||
|     dns-packet "^5.2.2" | ||||
|     thunky "^1.0.2" | ||||
| 
 | ||||
| mute-stream@0.0.8: | ||||
|   version "0.0.8" | ||||
|   resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-0.0.8.tgz#1630c42b2251ff81e2a283de96a5497ea92e5e0d" | ||||
|   integrity sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA== | ||||
| 
 | ||||
| nanoid@^3.3.1: | ||||
|   version "3.3.2" | ||||
|   resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.2.tgz#c89622fafb4381cd221421c69ec58547a1eec557" | ||||
| @ -6740,6 +6910,13 @@ no-case@^3.0.4: | ||||
|     lower-case "^2.0.2" | ||||
|     tslib "^2.0.3" | ||||
| 
 | ||||
| node-fetch@^2.6.7: | ||||
|   version "2.6.7" | ||||
|   resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-2.6.7.tgz#24de9fba827e3b4ae44dc8b20256a379160052ad" | ||||
|   integrity sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ== | ||||
|   dependencies: | ||||
|     whatwg-url "^5.0.0" | ||||
| 
 | ||||
| node-forge@^1: | ||||
|   version "1.3.1" | ||||
|   resolved "https://registry.yarnpkg.com/node-forge/-/node-forge-1.3.1.tgz#be8da2af243b2417d5f646a770663a92b7e9ded3" | ||||
| @ -6934,11 +7111,36 @@ optionator@^0.9.1: | ||||
|     type-check "^0.4.0" | ||||
|     word-wrap "^1.2.3" | ||||
| 
 | ||||
| ora@^5.4.1: | ||||
|   version "5.4.1" | ||||
|   resolved "https://registry.yarnpkg.com/ora/-/ora-5.4.1.tgz#1b2678426af4ac4a509008e5e4ac9e9959db9e18" | ||||
|   integrity sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ== | ||||
|   dependencies: | ||||
|     bl "^4.1.0" | ||||
|     chalk "^4.1.0" | ||||
|     cli-cursor "^3.1.0" | ||||
|     cli-spinners "^2.5.0" | ||||
|     is-interactive "^1.0.0" | ||||
|     is-unicode-supported "^0.1.0" | ||||
|     log-symbols "^4.1.0" | ||||
|     strip-ansi "^6.0.0" | ||||
|     wcwidth "^1.0.1" | ||||
| 
 | ||||
| os-tmpdir@~1.0.2: | ||||
|   version "1.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" | ||||
|   integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= | ||||
| 
 | ||||
| ospath@^1.2.2: | ||||
|   version "1.2.2" | ||||
|   resolved "https://registry.yarnpkg.com/ospath/-/ospath-1.2.2.tgz#1276639774a3f8ef2572f7fe4280e0ea4550c07b" | ||||
|   integrity sha1-EnZjl3Sj+O8lcvf+QoDg6kVQwHs= | ||||
| 
 | ||||
| outvariant@^1.2.1: | ||||
|   version "1.3.0" | ||||
|   resolved "https://registry.yarnpkg.com/outvariant/-/outvariant-1.3.0.tgz#c39723b1d2cba729c930b74bf962317a81b9b1c9" | ||||
|   integrity sha512-yeWM9k6UPfG/nzxdaPlJkB2p08hCg4xP6Lx99F+vP8YF7xyZVfTmJjrrNalkmzudD4WFvNLVudQikqUmF8zhVQ== | ||||
| 
 | ||||
| p-limit@^1.1.0: | ||||
|   version "1.3.0" | ||||
|   resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-1.3.0.tgz#b86bd5f0c25690911c7590fcbfc2010d54b3ccb8" | ||||
| @ -7093,6 +7295,11 @@ path-to-regexp@^1.7.0: | ||||
|   dependencies: | ||||
|     isarray "0.0.1" | ||||
| 
 | ||||
| path-to-regexp@^6.2.0: | ||||
|   version "6.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-6.2.0.tgz#f7b3803336104c346889adece614669230645f38" | ||||
|   integrity sha512-f66KywYG6+43afgE/8j/GoiNyygk/bnoCbps++3ErRKsIYkGGupyv07R2Ok5m9i67Iqc+T2g1eAUGUPzWhYTyg== | ||||
| 
 | ||||
| path-type@^4.0.0: | ||||
|   version "4.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" | ||||
| @ -8097,7 +8304,7 @@ readable-stream@^2.0.1: | ||||
|     string_decoder "~1.1.1" | ||||
|     util-deprecate "~1.0.1" | ||||
| 
 | ||||
| readable-stream@^3.0.6: | ||||
| readable-stream@^3.0.6, readable-stream@^3.4.0: | ||||
|   version "3.6.0" | ||||
|   resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-3.6.0.tgz#337bbda3adc0706bd3e024426a286d4b4b2c9198" | ||||
|   integrity sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA== | ||||
| @ -8341,6 +8548,11 @@ rollup@^2.43.1: | ||||
|   optionalDependencies: | ||||
|     fsevents "~2.3.2" | ||||
| 
 | ||||
| run-async@^2.4.0: | ||||
|   version "2.4.1" | ||||
|   resolved "https://registry.yarnpkg.com/run-async/-/run-async-2.4.1.tgz#8440eccf99ea3e70bd409d49aab88e10c189a455" | ||||
|   integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ== | ||||
| 
 | ||||
| run-parallel@^1.1.9: | ||||
|   version "1.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" | ||||
| @ -8348,7 +8560,7 @@ run-parallel@^1.1.9: | ||||
|   dependencies: | ||||
|     queue-microtask "^1.2.2" | ||||
| 
 | ||||
| rxjs@^7.5.1: | ||||
| rxjs@^7.5.1, rxjs@^7.5.5: | ||||
|   version "7.5.5" | ||||
|   resolved "https://registry.yarnpkg.com/rxjs/-/rxjs-7.5.5.tgz#2ebad89af0f560f460ad5cc4213219e1f7dd4e9f" | ||||
|   integrity sha512-sy+H0pQofO95VDmFLzyaw9xNJU4KTRSwQIGM6+iG3SypAtCiLDzpeG8sJrNCWn2Up9km+KhkvTdbkrdy+yzZdw== | ||||
| @ -8466,7 +8678,7 @@ semver@7.0.0: | ||||
|   resolved "https://registry.yarnpkg.com/semver/-/semver-7.0.0.tgz#5f3ca35761e47e05b206c6daff2cf814f0316b8e" | ||||
|   integrity sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A== | ||||
| 
 | ||||
| semver@7.3.6: | ||||
| semver@7.3.6, semver@^7.3.2, semver@^7.3.5: | ||||
|   version "7.3.6" | ||||
|   resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.6.tgz#5d73886fb9c0c6602e79440b97165c29581cbb2b" | ||||
|   integrity sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w== | ||||
| @ -8478,13 +8690,6 @@ semver@^6.0.0, semver@^6.1.1, semver@^6.1.2, semver@^6.3.0: | ||||
|   resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" | ||||
|   integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== | ||||
| 
 | ||||
| semver@^7.3.2, semver@^7.3.5: | ||||
|   version "7.3.6" | ||||
|   resolved "https://registry.yarnpkg.com/semver/-/semver-7.3.6.tgz#5d73886fb9c0c6602e79440b97165c29581cbb2b" | ||||
|   integrity sha512-HZWqcgwLsjaX1HBD31msI/rXktuIhS+lWvdE4kN9z+8IVT4Itc7vqU2WvYsyD6/sjYCt4dEKH/m1M3dwI9CC5w== | ||||
|   dependencies: | ||||
|     lru-cache "^7.4.0" | ||||
| 
 | ||||
| send@0.17.2: | ||||
|   version "0.17.2" | ||||
|   resolved "https://registry.yarnpkg.com/send/-/send-0.17.2.tgz#926622f76601c41808012c8bf1688fe3906f7820" | ||||
| @ -8541,6 +8746,11 @@ serve-static@1.14.2: | ||||
|     parseurl "~1.3.3" | ||||
|     send "0.17.2" | ||||
| 
 | ||||
| set-cookie-parser@^2.4.6: | ||||
|   version "2.4.8" | ||||
|   resolved "https://registry.yarnpkg.com/set-cookie-parser/-/set-cookie-parser-2.4.8.tgz#d0da0ed388bc8f24e706a391f9c9e252a13c58b2" | ||||
|   integrity sha512-edRH8mBKEWNVIVMKejNnuJxleqYE/ZSdcT8/Nem9/mmosx12pctd80s2Oy00KNZzrogMZS5mauK2/ymL1bvlvg== | ||||
| 
 | ||||
| setprototypeof@1.1.0: | ||||
|   version "1.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" | ||||
| @ -8751,6 +8961,18 @@ stackframe@^1.1.1: | ||||
|   resolved "https://registry.yarnpkg.com/statuses/-/statuses-1.5.0.tgz#161c7dac177659fd9811f43771fa99381478628c" | ||||
|   integrity sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= | ||||
| 
 | ||||
| statuses@^2.0.0: | ||||
|   version "2.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/statuses/-/statuses-2.0.1.tgz#55cb000ccf1d48728bd23c685a063998cf1a1b63" | ||||
|   integrity sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ== | ||||
| 
 | ||||
| strict-event-emitter@^0.2.0: | ||||
|   version "0.2.4" | ||||
|   resolved "https://registry.yarnpkg.com/strict-event-emitter/-/strict-event-emitter-0.2.4.tgz#365714f0c95f059db31064ca745d5b33e5b30f6e" | ||||
|   integrity sha512-xIqTLS5azUH1djSUsLH9DbP6UnM/nI18vu8d43JigCQEoVsnY+mrlE+qv6kYqs6/1OkMnMIiL6ffedQSZStuoQ== | ||||
|   dependencies: | ||||
|     events "^3.3.0" | ||||
| 
 | ||||
| string-length@^4.0.1: | ||||
|   version "4.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/string-length/-/string-length-4.0.2.tgz#a8a8dc7bd5c1a82b9b3c8b87e125f66871b6e57a" | ||||
| @ -8772,7 +8994,7 @@ string-natural-compare@^3.0.1: | ||||
|   resolved "https://registry.yarnpkg.com/string-natural-compare/-/string-natural-compare-3.0.1.tgz#7a42d58474454963759e8e8b7ae63d71c1e7fdf4" | ||||
|   integrity sha512-n3sPwynL1nwKi3WJ6AIsClwBMa0zTi54fn2oLU6ndfTSIO05xaznjSf15PcBZU6FNWbmN5Q6cxT4V5hGvB4taw== | ||||
| 
 | ||||
| string-width@^4.1.0, string-width@^4.2.0: | ||||
| string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: | ||||
|   version "4.2.3" | ||||
|   resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" | ||||
|   integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== | ||||
| @ -9079,7 +9301,7 @@ throttleit@^1.0.0: | ||||
|   resolved "https://registry.yarnpkg.com/throttleit/-/throttleit-1.0.0.tgz#9e785836daf46743145a5984b6268d828528ac6c" | ||||
|   integrity sha1-nnhYNtr0Z0MUWlmEtiaNgoUorGw= | ||||
| 
 | ||||
| through@^2.3.8: | ||||
| through@^2.3.6, through@^2.3.8: | ||||
|   version "2.3.8" | ||||
|   resolved "https://registry.yarnpkg.com/through/-/through-2.3.8.tgz#0dd4c9ffaabc357960b1b724115d7e0e86a2e1f5" | ||||
|   integrity sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= | ||||
| @ -9099,6 +9321,13 @@ tiny-warning@^1.0.0, tiny-warning@^1.0.2, tiny-warning@^1.0.3: | ||||
|   resolved "https://registry.yarnpkg.com/tiny-warning/-/tiny-warning-1.0.3.tgz#94a30db453df4c643d0fd566060d60a875d84754" | ||||
|   integrity sha512-lBN9zLN/oAf68o3zNXYrdCt1kP8WsiGW8Oo2ka41b2IM5JL/S1CTyX1rW0mb/zSuJun0ZUrDxx4sqvYS2FWzPA== | ||||
| 
 | ||||
| tmp@^0.0.33: | ||||
|   version "0.0.33" | ||||
|   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" | ||||
|   integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== | ||||
|   dependencies: | ||||
|     os-tmpdir "~1.0.2" | ||||
| 
 | ||||
| tmp@~0.2.1: | ||||
|   version "0.2.1" | ||||
|   resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.2.1.tgz#8457fc3037dcf4719c251367a1af6500ee1ccf14" | ||||
| @ -9164,6 +9393,11 @@ tr46@^2.1.0: | ||||
|   dependencies: | ||||
|     punycode "^2.1.1" | ||||
| 
 | ||||
| tr46@~0.0.3: | ||||
|   version "0.0.3" | ||||
|   resolved "https://registry.yarnpkg.com/tr46/-/tr46-0.0.3.tgz#8184fd347dac9cdc185992f3a6622e14b9d9ab6a" | ||||
|   integrity sha1-gYT9NH2snNwYWZLzpmIuFLnZq2o= | ||||
| 
 | ||||
| tryer@^1.0.1: | ||||
|   version "1.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/tryer/-/tryer-1.0.1.tgz#f2c85406800b9b0f74c9f7465b81eaad241252f8" | ||||
| @ -9242,6 +9476,11 @@ type-fest@^0.21.3: | ||||
|   resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" | ||||
|   integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== | ||||
| 
 | ||||
| type-fest@^1.2.2: | ||||
|   version "1.4.0" | ||||
|   resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-1.4.0.tgz#e9fb813fe3bf1744ec359d55d1affefa76f14be1" | ||||
|   integrity sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA== | ||||
| 
 | ||||
| type-is@~1.6.18: | ||||
|   version "1.6.18" | ||||
|   resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.18.tgz#4e552cd05df09467dcbc4ef739de89f2cf37c131" | ||||
| @ -9438,6 +9677,18 @@ wbuf@^1.1.0, wbuf@^1.7.3: | ||||
|   dependencies: | ||||
|     minimalistic-assert "^1.0.0" | ||||
| 
 | ||||
| wcwidth@^1.0.1: | ||||
|   version "1.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/wcwidth/-/wcwidth-1.0.1.tgz#f0b0dcf915bc5ff1528afadb2c0e17b532da2fe8" | ||||
|   integrity sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= | ||||
|   dependencies: | ||||
|     defaults "^1.0.3" | ||||
| 
 | ||||
| webidl-conversions@^3.0.0: | ||||
|   version "3.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" | ||||
|   integrity sha1-JFNCdeKnvGvnvIZhHMFq4KVlSHE= | ||||
| 
 | ||||
| webidl-conversions@^4.0.2: | ||||
|   version "4.0.2" | ||||
|   resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" | ||||
| @ -9589,6 +9840,14 @@ whatwg-mimetype@^2.3.0: | ||||
|   resolved "https://registry.yarnpkg.com/whatwg-mimetype/-/whatwg-mimetype-2.3.0.tgz#3d4b1e0312d2079879f826aff18dbeeca5960fbf" | ||||
|   integrity sha512-M4yMwr6mAnQz76TbJm914+gPpB/nCwvZbJU28cUD6dR004SAxDLOOSUaB1JDRqLtaOV/vi0IC5lEAGFgrjGv/g== | ||||
| 
 | ||||
| whatwg-url@^5.0.0: | ||||
|   version "5.0.0" | ||||
|   resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" | ||||
|   integrity sha1-lmRU6HZUYuN2RNNib2dCzotwll0= | ||||
|   dependencies: | ||||
|     tr46 "~0.0.3" | ||||
|     webidl-conversions "^3.0.0" | ||||
| 
 | ||||
| whatwg-url@^7.0.0: | ||||
|   version "7.1.0" | ||||
|   resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-7.1.0.tgz#c2c492f1eca612988efd3d2266be1b9fc6170d06" | ||||
| @ -9879,6 +10138,11 @@ yargs-parser@^20.2.2: | ||||
|   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" | ||||
|   integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== | ||||
| 
 | ||||
| yargs-parser@^21.0.0: | ||||
|   version "21.0.1" | ||||
|   resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.0.1.tgz#0267f286c877a4f0f728fceb6f8a3e4cb95c6e35" | ||||
|   integrity sha512-9BK1jFpLzJROCI5TzwZL/TU4gqjK5xiHV/RfWLOahrjAko/e4DJkRDZQXfvqAsiZzzYhgAzbgz6lg48jcm4GLg== | ||||
| 
 | ||||
| yargs@^16.2.0: | ||||
|   version "16.2.0" | ||||
|   resolved "https://registry.yarnpkg.com/yargs/-/yargs-16.2.0.tgz#1c82bf0f6b6a66eafce7ef30e376f49a12477f66" | ||||
| @ -9892,6 +10156,19 @@ yargs@^16.2.0: | ||||
|     y18n "^5.0.5" | ||||
|     yargs-parser "^20.2.2" | ||||
| 
 | ||||
| yargs@^17.3.1: | ||||
|   version "17.4.0" | ||||
|   resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.4.0.tgz#9fc9efc96bd3aa2c1240446af28499f0e7593d00" | ||||
|   integrity sha512-WJudfrk81yWFSOkZYpAZx4Nt7V4xp7S/uJkX0CnxovMCt1wCE8LNftPpNuF9X/u9gN5nsD7ycYtRcDf2pL3UiA== | ||||
|   dependencies: | ||||
|     cliui "^7.0.2" | ||||
|     escalade "^3.1.1" | ||||
|     get-caller-file "^2.0.5" | ||||
|     require-directory "^2.1.1" | ||||
|     string-width "^4.2.3" | ||||
|     y18n "^5.0.5" | ||||
|     yargs-parser "^21.0.0" | ||||
| 
 | ||||
| yauzl@^2.10.0: | ||||
|   version "2.10.0" | ||||
|   resolved "https://registry.yarnpkg.com/yauzl/-/yauzl-2.10.0.tgz#c7eb17c93e112cb1086fa6d8e51fb0667b79a5f9" | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user