feat(tests): add e2e tests for widgets (#8735)
* test(e2e): add baseline for widget tests * chore(repo): enable test running in branch * fix(e2e): set viewport for widget tests * fix(client): add widget identifier classes to widgets * test(e2e): add memo widget test * fix(tests): force select value * fix(tests): force button press for widget addition * fix(tests): invoke select value differently * fix(tests): adjust widget submit * fix(tests): don't explicitly navigate for widget test * fix(tests): click label to hide select popup * fix(tests): just click modal background * fix(tests): adjust modal background selector * fix(tests): click all modal backgrounds * feat(e2e): add test for adding timeline widget * fix(client): add more widget identifier classes * feat(tests): add method abstraction for test cases * fix(tests): force-click overlays * fix(tests): force widget button press * fix(tests): remove timeout from final widget check * feat(tests): add widget removal test case * fix(client): use mk instead of msky as class prefix * fix(tests): check widgets for existence rather than visibility * chore(meta): don't run tests for specific feature branch
This commit is contained in:
		
							parent
							
								
									1c057818c6
								
							
						
					
					
						commit
						708fba989a
					
				
					 16 changed files with 100 additions and 16 deletions
				
			
		
							
								
								
									
										84
									
								
								cypress/integration/widgets.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								cypress/integration/widgets.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,84 @@ | |||
| describe('After user signed in', () => { | ||||
| 	beforeEach(() => { | ||||
| 		cy.window(win => { | ||||
| 			win.indexedDB.deleteDatabase('keyval-store'); | ||||
| 		}); | ||||
| 		cy.viewport('macbook-16'); | ||||
| 		cy.request('POST', '/api/reset-db').as('reset'); | ||||
| 		cy.get('@reset').its('status').should('equal', 204); | ||||
| 		cy.reload(true); | ||||
| 
 | ||||
| 		// インスタンス初期セットアップ
 | ||||
| 		cy.request('POST', '/api/admin/accounts/create', { | ||||
| 			username: 'admin', | ||||
| 			password: 'pass', | ||||
| 		}).its('body').as('admin'); | ||||
| 
 | ||||
| 		// ユーザー作成
 | ||||
| 		cy.request('POST', '/api/signup', { | ||||
| 			username: 'alice', | ||||
| 			password: 'alice1234', | ||||
| 		}).its('body').as('alice'); | ||||
| 
 | ||||
| 		cy.visit('/'); | ||||
| 
 | ||||
| 		cy.intercept('POST', '/api/signin').as('signin'); | ||||
| 
 | ||||
| 		cy.get('[data-cy-signin]').click(); | ||||
| 		cy.get('[data-cy-signin-username] input').type('alice'); | ||||
| 		cy.get('[data-cy-signin-password] input').type('alice1234{enter}'); | ||||
| 
 | ||||
| 		cy.wait('@signin').as('signedIn'); | ||||
| 	}); | ||||
| 
 | ||||
| 	afterEach(() => { | ||||
| 		// テスト終了直前にページ遷移するようなテストケース(例えばアカウント作成)だと、たぶんCypressのバグでブラウザの内容が次のテストケースに引き継がれてしまう(例えばアカウントが作成し終わった段階からテストが始まる)。
 | ||||
| 		// waitを入れることでそれを防止できる
 | ||||
| 		cy.wait(1000); | ||||
| 	}); | ||||
| 
 | ||||
|   it('widget edit toggle is visible', () => { | ||||
| 		cy.get('.mk-widget-edit').should('be.visible'); | ||||
|   }); | ||||
| 
 | ||||
| 	it('widget select should be visible in edit mode', () => { | ||||
| 		cy.get('.mk-widget-edit').click(); | ||||
| 		cy.get('.mk-widget-select').should('be.visible'); | ||||
|   }); | ||||
| 
 | ||||
| 	it('first widget should be removed', () => { | ||||
| 		cy.get('.mk-widget-edit').click(); | ||||
| 		cy.get('.customize-container:first-child .remove._button').click(); | ||||
| 		cy.get('.customize-container').should('have.length', 2); | ||||
| 	}); | ||||
| 
 | ||||
| 	function buildWidgetTest(widgetName) { | ||||
| 		it(`${widgetName} widget should get added`, () => { | ||||
| 			cy.get('.mk-widget-edit').click(); | ||||
| 			cy.get('.mk-widget-select select').select(widgetName, { force: true }); | ||||
| 			cy.get('.bg._modalBg.transparent').click({ multiple: true, force: true }); | ||||
| 			cy.get('.mk-widget-add').click({ force: true }); | ||||
| 			cy.get(`.mkw-${widgetName}`).should('exist'); | ||||
| 		}); | ||||
| 	} | ||||
| 
 | ||||
| 	buildWidgetTest('memo'); | ||||
| 	buildWidgetTest('notifications'); | ||||
| 	buildWidgetTest('timeline'); | ||||
| 	buildWidgetTest('calendar'); | ||||
| 	buildWidgetTest('rss'); | ||||
| 	buildWidgetTest('trends'); | ||||
| 	buildWidgetTest('clock'); | ||||
| 	buildWidgetTest('activity'); | ||||
| 	buildWidgetTest('photos'); | ||||
| 	buildWidgetTest('digitalClock'); | ||||
| 	buildWidgetTest('federation'); | ||||
| 	buildWidgetTest('postForm'); | ||||
| 	buildWidgetTest('slideshow'); | ||||
| 	buildWidgetTest('serverMetric'); | ||||
| 	buildWidgetTest('onlineUsers'); | ||||
| 	buildWidgetTest('jobQueue'); | ||||
| 	buildWidgetTest('button'); | ||||
| 	buildWidgetTest('aiscript'); | ||||
| 	buildWidgetTest('aichan'); | ||||
| }); | ||||
|  | @ -2,11 +2,11 @@ | |||
| <div class="vjoppmmu"> | ||||
| 	<template v-if="edit"> | ||||
| 		<header> | ||||
| 			<MkSelect v-model="widgetAdderSelected" style="margin-bottom: var(--margin)"> | ||||
| 			<MkSelect v-model="widgetAdderSelected" style="margin-bottom: var(--margin)" class="mk-widget-select"> | ||||
| 				<template #label>{{ $ts.selectWidget }}</template> | ||||
| 				<option v-for="widget in widgetDefs" :key="widget" :value="widget">{{ $t(`_widgets.${widget}`) }}</option> | ||||
| 			</MkSelect> | ||||
| 			<MkButton inline primary @click="addWidget"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton> | ||||
| 			<MkButton inline primary class="mk-widget-add" @click="addWidget"><i class="fas fa-plus"></i> {{ $ts.add }}</MkButton> | ||||
| 			<MkButton inline @click="$emit('exit')">{{ $ts.close }}</MkButton> | ||||
| 		</header> | ||||
| 		<XDraggable | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ | |||
| 	<XWidgets :edit="editMode" :widgets="defaultStore.reactiveState.widgets.value" @add-widget="addWidget" @remove-widget="removeWidget" @update-widget="updateWidget" @update-widgets="updateWidgets" @exit="editMode = false"/> | ||||
| 
 | ||||
| 	<button v-if="editMode" class="_textButton" style="font-size: 0.9em;" @click="editMode = false"><i class="fas fa-check"></i> {{ i18n.ts.editWidgetsExit }}</button> | ||||
| 	<button v-else class="_textButton" style="font-size: 0.9em;" @click="editMode = true"><i class="fas fa-pencil-alt"></i> {{ i18n.ts.editWidgets }}</button> | ||||
| 	<button v-else class="_textButton mk-widget-edit" style="font-size: 0.9em;" @click="editMode = true"><i class="fas fa-pencil-alt"></i> {{ i18n.ts.editWidgets }}</button> | ||||
| </div> | ||||
| </template> | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :show-header="widgetProps.showHeader" :naked="widgetProps.transparent"> | ||||
| <MkContainer :show-header="widgetProps.showHeader" :naked="widgetProps.transparent" class="mkw-activity"> | ||||
| 	<template #header><i class="fas fa-chart-bar"></i>{{ $ts._widgets.activity }}</template> | ||||
| 	<template #func><button class="_button" @click="toggleView()"><i class="fas fa-sort"></i></button></template> | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :naked="widgetProps.transparent" :show-header="false"> | ||||
| <MkContainer :naked="widgetProps.transparent" :show-header="false" class="mkw-aichan"> | ||||
| 	<iframe ref="live2d" class="dedjhjmo" src="https://misskey-dev.github.io/mascot-web/?scale=1.5&y=1.1&eyeY=100" @click="touched"></iframe> | ||||
| </MkContainer> | ||||
| </template> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :show-header="widgetProps.showHeader"> | ||||
| <MkContainer :show-header="widgetProps.showHeader" class="mkw-aiscript"> | ||||
| 	<template #header><i class="fas fa-terminal"></i>{{ $ts._widgets.aiscript }}</template> | ||||
| 
 | ||||
| 	<div class="uylguesu _monospace"> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :naked="widgetProps.transparent" :show-header="false"> | ||||
| <MkContainer :naked="widgetProps.transparent" :show-header="false" class="mkw-clock"> | ||||
| 	<div class="vubelbmv"> | ||||
| 		<MkAnalogClock class="clock" :thickness="widgetProps.thickness"/> | ||||
| 	</div> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :show-header="widgetProps.showHeader" :foldable="foldable" :scrollable="scrollable"> | ||||
| <MkContainer :show-header="widgetProps.showHeader" :foldable="foldable" :scrollable="scrollable" class="mkw-federation"> | ||||
| 	<template #header><i class="fas fa-globe"></i>{{ $ts._widgets.federation }}</template> | ||||
| 
 | ||||
| 	<div class="wbrkwalb"> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :show-header="widgetProps.showHeader"> | ||||
| <MkContainer :show-header="widgetProps.showHeader" class="mkw-memo"> | ||||
| 	<template #header><i class="fas fa-sticky-note"></i>{{ $ts._widgets.memo }}</template> | ||||
| 
 | ||||
| 	<div class="otgbylcu"> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :style="`height: ${widgetProps.height}px;`" :show-header="widgetProps.showHeader" :scrollable="true"> | ||||
| <MkContainer :style="`height: ${widgetProps.height}px;`" :show-header="widgetProps.showHeader" :scrollable="true" class="mkw-notifications"> | ||||
| 	<template #header><i class="fas fa-bell"></i>{{ $ts.notifications }}</template> | ||||
| 	<template #func><button class="_button" @click="configureNotification()"><i class="fas fa-cog"></i></button></template> | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :show-header="widgetProps.showHeader" :naked="widgetProps.transparent" :class="$style.root" :data-transparent="widgetProps.transparent ? true : null"> | ||||
| <MkContainer :show-header="widgetProps.showHeader" :naked="widgetProps.transparent" :class="$style.root" :data-transparent="widgetProps.transparent ? true : null" class="mkw-photos"> | ||||
| 	<template #header><i class="fas fa-camera"></i>{{ $ts._widgets.photos }}</template> | ||||
| 
 | ||||
| 	<div class=""> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <XPostForm class="_panel" :fixed="true" :autofocus="false"/> | ||||
| <XPostForm class="_panel mkw-postForm" :fixed="true" :autofocus="false"/> | ||||
| </template> | ||||
| 
 | ||||
| <script lang="ts" setup> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :show-header="widgetProps.showHeader"> | ||||
| <MkContainer :show-header="widgetProps.showHeader" class="mkw-rss"> | ||||
| 	<template #header><i class="fas fa-rss-square"></i>RSS</template> | ||||
| 	<template #func><button class="_button" @click="configure"><i class="fas fa-cog"></i></button></template> | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <div class="kvausudm _panel" :style="{ height: widgetProps.height + 'px' }"> | ||||
| <div class="kvausudm _panel mkw-slideshow" :style="{ height: widgetProps.height + 'px' }"> | ||||
| 	<div @click="choose"> | ||||
| 		<p v-if="widgetProps.folderId == null"> | ||||
| 			{{ $ts.folder }} | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :show-header="widgetProps.showHeader" :style="`height: ${widgetProps.height}px;`" :scrollable="true"> | ||||
| <MkContainer :show-header="widgetProps.showHeader" :style="`height: ${widgetProps.height}px;`" :scrollable="true" class="mkw-timeline"> | ||||
| 	<template #header> | ||||
| 		<button class="_button" @click="choose"> | ||||
| 			<i v-if="widgetProps.src === 'home'" class="fas fa-home"></i> | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| <template> | ||||
| <MkContainer :show-header="widgetProps.showHeader"> | ||||
| <MkContainer :show-header="widgetProps.showHeader" class="mkw-trends"> | ||||
| 	<template #header><i class="fas fa-hashtag"></i>{{ $ts._widgets.trends }}</template> | ||||
| 
 | ||||
| 	<div class="wbrkwala"> | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue