enhance: e2eテストをできるだけ改良してみた (#8159)
* update docker image?
* 続
* serial run delete from "${table}" cascade
* use cypress official github action
* refuse install by cypress action
* clean up
* use wait?
* use more wait?
* Revert "use more wait?"
This reverts commit 18d0fcae9c7d8f98a4cafb4a846a031ece57350c.
* Revert "use wait?"
This reverts commit 5aa8feec9cdc3e2f79e566249f0a0eff6c0df6a0.
* fix
* test
* test
* log?
* 握りつぶしてみる
* clean up
* env?
* clean up?
* disable video
* add comment
* remove test
* 成功?
* test browser
* nodeインストール無効化
* node16.13.0-chrome95-ff94
* node.js復活
* ?
* ちょっと戻してみる
* chrome?
* cross browser test2
* --shm-size=2g
* artifact?
* misskey.local?
* firefoxはあきらめる
* not headless?
* oops
* fix
* ??
* test1
* if?
* fail-fast: false
* headless: false
* easy error ignoreing describe
* エラーの解消
とちょっとリファクター
* add browser name to artifact
* Install mplayer for FireFox
* no wait?
* タイムアウトを甘くしてみる
* firefoxをあきらめる(n回目)
* remove timeout setting
* wait復活
* Update basic.js
* Update index.js
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
			
			
This commit is contained in:
		
							parent
							
								
									cbb7e95d82
								
							
						
					
					
						commit
						e1d69e236f
					
				
					 10 changed files with 99 additions and 71 deletions
				
			
		
							
								
								
									
										39
									
								
								.github/workflows/test.yml
									
										
									
									
										vendored
									
									
								
							
							
						
						
									
										39
									
								
								.github/workflows/test.yml
									
										
									
									
										vendored
									
									
								
							| 
						 | 
					@ -17,14 +17,14 @@ jobs:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    services:
 | 
					    services:
 | 
				
			||||||
      postgres:
 | 
					      postgres:
 | 
				
			||||||
        image: postgres:12.2-alpine
 | 
					        image: postgres:13
 | 
				
			||||||
        ports:
 | 
					        ports:
 | 
				
			||||||
          - 54312:5432
 | 
					          - 54312:5432
 | 
				
			||||||
        env:
 | 
					        env:
 | 
				
			||||||
          POSTGRES_DB: test-misskey
 | 
					          POSTGRES_DB: test-misskey
 | 
				
			||||||
          POSTGRES_HOST_AUTH_METHOD: trust
 | 
					          POSTGRES_HOST_AUTH_METHOD: trust
 | 
				
			||||||
      redis:
 | 
					      redis:
 | 
				
			||||||
        image: redis:4.0-alpine
 | 
					        image: redis:6
 | 
				
			||||||
        ports:
 | 
					        ports:
 | 
				
			||||||
          - 56312:6379
 | 
					          - 56312:6379
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,19 +51,21 @@ jobs:
 | 
				
			||||||
    runs-on: ubuntu-latest
 | 
					    runs-on: ubuntu-latest
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    strategy:
 | 
					    strategy:
 | 
				
			||||||
 | 
					      fail-fast: false
 | 
				
			||||||
      matrix:
 | 
					      matrix:
 | 
				
			||||||
        node-version: [16.x]
 | 
					        node-version: [16.x]
 | 
				
			||||||
 | 
					        browser: [chrome]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    services:
 | 
					    services:
 | 
				
			||||||
      postgres:
 | 
					      postgres:
 | 
				
			||||||
        image: postgres:12.2-alpine
 | 
					        image: postgres:13
 | 
				
			||||||
        ports:
 | 
					        ports:
 | 
				
			||||||
          - 54312:5432
 | 
					          - 54312:5432
 | 
				
			||||||
        env:
 | 
					        env:
 | 
				
			||||||
          POSTGRES_DB: test-misskey
 | 
					          POSTGRES_DB: test-misskey
 | 
				
			||||||
          POSTGRES_HOST_AUTH_METHOD: trust
 | 
					          POSTGRES_HOST_AUTH_METHOD: trust
 | 
				
			||||||
      redis:
 | 
					      redis:
 | 
				
			||||||
        image: redis:4.0-alpine
 | 
					        image: redis:6
 | 
				
			||||||
        ports:
 | 
					        ports:
 | 
				
			||||||
          - 56312:6379
 | 
					          - 56312:6379
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -71,6 +73,12 @@ jobs:
 | 
				
			||||||
    - uses: actions/checkout@v2
 | 
					    - uses: actions/checkout@v2
 | 
				
			||||||
      with:
 | 
					      with:
 | 
				
			||||||
        submodules: true
 | 
					        submodules: true
 | 
				
			||||||
 | 
					    # https://github.com/cypress-io/cypress-docker-images/issues/150
 | 
				
			||||||
 | 
					    #- name: Install mplayer for FireFox
 | 
				
			||||||
 | 
					    #  run: sudo apt install mplayer -y
 | 
				
			||||||
 | 
					    #  if: ${{ matrix.browser == 'firefox' }}
 | 
				
			||||||
 | 
					    #- uses: browser-actions/setup-firefox@latest
 | 
				
			||||||
 | 
					    #  if: ${{ matrix.browser == 'firefox' }}
 | 
				
			||||||
    - name: Use Node.js ${{ matrix.node-version }}
 | 
					    - name: Use Node.js ${{ matrix.node-version }}
 | 
				
			||||||
      uses: actions/setup-node@v1
 | 
					      uses: actions/setup-node@v1
 | 
				
			||||||
      with:
 | 
					      with:
 | 
				
			||||||
| 
						 | 
					@ -87,5 +95,24 @@ jobs:
 | 
				
			||||||
      run: cp .github/misskey/test.yml .config
 | 
					      run: cp .github/misskey/test.yml .config
 | 
				
			||||||
    - name: Build
 | 
					    - name: Build
 | 
				
			||||||
      run: yarn build
 | 
					      run: yarn build
 | 
				
			||||||
    - name: Test
 | 
					    # https://github.com/cypress-io/cypress/issues/4351#issuecomment-559489091
 | 
				
			||||||
      run: yarn e2e
 | 
					    - name: ALSA Env
 | 
				
			||||||
 | 
					      run: echo -e 'pcm.!default {\n type hw\n card 0\n}\n\nctl.!default {\n type hw\n card 0\n}' > ~/.asoundrc
 | 
				
			||||||
 | 
					    - name: Cypress run
 | 
				
			||||||
 | 
					      uses: cypress-io/github-action@v2
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        install: false
 | 
				
			||||||
 | 
					        start: npm run start:test
 | 
				
			||||||
 | 
					        wait-on: 'http://localhost:61812'
 | 
				
			||||||
 | 
					        headless: false
 | 
				
			||||||
 | 
					        browser: ${{ matrix.browser }}
 | 
				
			||||||
 | 
					    - uses: actions/upload-artifact@v2
 | 
				
			||||||
 | 
					      if: failure()
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        name: ${{ matrix.browser }}-cypress-screenshots
 | 
				
			||||||
 | 
					        path: cypress/screenshots
 | 
				
			||||||
 | 
					    - uses: actions/upload-artifact@v2
 | 
				
			||||||
 | 
					      if: always()
 | 
				
			||||||
 | 
					      with:
 | 
				
			||||||
 | 
					        name: ${{ matrix.browser }}-cypress-videos
 | 
				
			||||||
 | 
					        path: cypress/videos
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,8 +41,6 @@ describe('After setup instance', () => {
 | 
				
			||||||
			username: 'admin',
 | 
								username: 'admin',
 | 
				
			||||||
			password: 'pass',
 | 
								password: 'pass',
 | 
				
			||||||
		}).its('body').as('admin');
 | 
							}).its('body').as('admin');
 | 
				
			||||||
 | 
					 | 
				
			||||||
		cy.get('@admin');
 | 
					 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	afterEach(() => {
 | 
						afterEach(() => {
 | 
				
			||||||
| 
						 | 
					@ -82,15 +80,11 @@ describe('After user signup', () => {
 | 
				
			||||||
			password: 'pass',
 | 
								password: 'pass',
 | 
				
			||||||
		}).its('body').as('admin');
 | 
							}).its('body').as('admin');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cy.get('@admin').then(() => {
 | 
							// ユーザー作成
 | 
				
			||||||
			// ユーザー作成
 | 
							cy.request('POST', '/api/signup', {
 | 
				
			||||||
			cy.request('POST', '/api/signup', {
 | 
								username: 'alice',
 | 
				
			||||||
				username: 'alice',
 | 
								password: 'alice1234',
 | 
				
			||||||
				password: 'alice1234',
 | 
							}).its('body').as('alice');
 | 
				
			||||||
			}).its('body').as('alice');
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		cy.get('@alice');
 | 
					 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	afterEach(() => {
 | 
						afterEach(() => {
 | 
				
			||||||
| 
						 | 
					@ -145,27 +139,21 @@ describe('After user singed in', () => {
 | 
				
			||||||
			password: 'pass',
 | 
								password: 'pass',
 | 
				
			||||||
		}).its('body').as('admin');
 | 
							}).its('body').as('admin');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cy.get('@admin').then(() => {
 | 
							// ユーザー作成
 | 
				
			||||||
			// ユーザー作成
 | 
							cy.request('POST', '/api/signup', {
 | 
				
			||||||
			cy.request('POST', '/api/signup', {
 | 
								username: 'alice',
 | 
				
			||||||
				username: 'alice',
 | 
								password: 'alice1234',
 | 
				
			||||||
				password: 'alice1234',
 | 
							}).its('body').as('alice');
 | 
				
			||||||
			}).its('body').as('alice');
 | 
					 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		cy.get('@alice').then(() => {
 | 
							cy.visit('/');
 | 
				
			||||||
			cy.visit('/');
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			cy.intercept('POST', '/api/signin').as('signin');
 | 
							cy.intercept('POST', '/api/signin').as('signin');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			cy.get('[data-cy-signin]').click();
 | 
							cy.get('[data-cy-signin]').click();
 | 
				
			||||||
			cy.get('[data-cy-signin-username] input').type('alice');
 | 
							cy.get('[data-cy-signin-username] input').type('alice');
 | 
				
			||||||
			cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
 | 
							cy.get('[data-cy-signin-password] input').type('alice1234{enter}');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			cy.wait('@signin').as('signedIn');
 | 
							cy.wait('@signin').as('signedIn');
 | 
				
			||||||
		});
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		cy.get('@signedIn');
 | 
					 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	afterEach(() => {
 | 
						afterEach(() => {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -20,7 +20,13 @@ import './commands'
 | 
				
			||||||
// require('./commands')
 | 
					// require('./commands')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
Cypress.on('uncaught:exception', (err, runnable) => {
 | 
					Cypress.on('uncaught:exception', (err, runnable) => {
 | 
				
			||||||
  if (err.message.includes('ResizeObserver loop limit exceeded')) {
 | 
						if ([
 | 
				
			||||||
    return false
 | 
							// Chrome
 | 
				
			||||||
  }
 | 
							'ResizeObserver loop limit exceeded',
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Firefox
 | 
				
			||||||
 | 
							'ResizeObserver loop completed with undelivered notifications',
 | 
				
			||||||
 | 
						].some(msg => err.message.includes(msg))) {
 | 
				
			||||||
 | 
							return false;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -220,7 +220,9 @@ export async function resetDb() {
 | 
				
			||||||
		WHERE nspname NOT IN ('pg_catalog', 'information_schema')
 | 
							WHERE nspname NOT IN ('pg_catalog', 'information_schema')
 | 
				
			||||||
			AND C.relkind = 'r'
 | 
								AND C.relkind = 'r'
 | 
				
			||||||
			AND nspname !~ '^pg_toast';`);
 | 
								AND nspname !~ '^pg_toast';`);
 | 
				
			||||||
		await Promise.all(tables.map(t => t.table).map(x => conn.query(`DELETE FROM "${x}" CASCADE`)));
 | 
							for (const table of tables) {
 | 
				
			||||||
 | 
								await conn.query(`DELETE FROM "${table.table}" CASCADE`);
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	};
 | 
						};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (let i = 1; i <= 3; i++) {
 | 
						for (let i = 1; i <= 3; i++) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,12 +2,12 @@ version: "3"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
services:
 | 
					services:
 | 
				
			||||||
  redistest:
 | 
					  redistest:
 | 
				
			||||||
    image: redis:4.0-alpine
 | 
					    image: redis:6
 | 
				
			||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
      - "127.0.0.1:56312:6379"
 | 
					      - "127.0.0.1:56312:6379"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  dbtest:
 | 
					  dbtest:
 | 
				
			||||||
    image: postgres:12.2-alpine
 | 
					    image: postgres:13
 | 
				
			||||||
    ports:
 | 
					    ports:
 | 
				
			||||||
      - "127.0.0.1:54312:5432"
 | 
					      - "127.0.0.1:54312:5432"
 | 
				
			||||||
    environment:
 | 
					    environment:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -32,9 +32,7 @@ const props = defineProps<{
 | 
				
			||||||
const pagingComponent = ref<InstanceType<typeof MkPagination>>();
 | 
					const pagingComponent = ref<InstanceType<typeof MkPagination>>();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineExpose({
 | 
					defineExpose({
 | 
				
			||||||
	prepend: (note) => {
 | 
						pagingComponent,
 | 
				
			||||||
		pagingComponent.value?.prepend(note);
 | 
					 | 
				
			||||||
	},
 | 
					 | 
				
			||||||
});
 | 
					});
 | 
				
			||||||
</script>
 | 
					</script>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -25,10 +25,10 @@ const emit = defineEmits<{
 | 
				
			||||||
 | 
					
 | 
				
			||||||
provide('inChannel', computed(() => props.src === 'channel'));
 | 
					provide('inChannel', computed(() => props.src === 'channel'));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const tlComponent = ref<InstanceType<typeof XNotes>>();
 | 
					const tlComponent: InstanceType<typeof XNotes> = $ref();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const prepend = note => {
 | 
					const prepend = note => {
 | 
				
			||||||
	tlComponent.value.prepend(note);
 | 
						tlComponent.pagingComponent?.prepend(note);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	emit('note');
 | 
						emit('note');
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -38,16 +38,16 @@ const prepend = note => {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const onUserAdded = () => {
 | 
					const onUserAdded = () => {
 | 
				
			||||||
	tlComponent.value.reload();
 | 
						tlComponent.pagingComponent?.reload();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const onUserRemoved = () => {
 | 
					const onUserRemoved = () => {
 | 
				
			||||||
	tlComponent.value.reload();
 | 
						tlComponent.pagingComponent?.reload();
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const onChangeFollowing = () => {
 | 
					const onChangeFollowing = () => {
 | 
				
			||||||
	if (!tlComponent.value.backed) {
 | 
						if (!tlComponent.pagingComponent?.backed) {
 | 
				
			||||||
		tlComponent.value.reload();
 | 
							tlComponent.pagingComponent?.reload();
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -73,12 +73,11 @@ const queue = ref<Item[]>([]);
 | 
				
			||||||
const offset = ref(0);
 | 
					const offset = ref(0);
 | 
				
			||||||
const fetching = ref(true);
 | 
					const fetching = ref(true);
 | 
				
			||||||
const moreFetching = ref(false);
 | 
					const moreFetching = ref(false);
 | 
				
			||||||
const inited = ref(false);
 | 
					 | 
				
			||||||
const more = ref(false);
 | 
					const more = ref(false);
 | 
				
			||||||
const backed = ref(false); // 遡り中か否か
 | 
					const backed = ref(false); // 遡り中か否か
 | 
				
			||||||
const isBackTop = ref(false);
 | 
					const isBackTop = ref(false);
 | 
				
			||||||
const empty = computed(() => items.value.length === 0 && !fetching.value && inited.value);
 | 
					const empty = computed(() => items.value.length === 0);
 | 
				
			||||||
const error = computed(() => !fetching.value && !inited.value);
 | 
					const error = ref(false);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const init = async (): Promise<void> => {
 | 
					const init = async (): Promise<void> => {
 | 
				
			||||||
	queue.value = [];
 | 
						queue.value = [];
 | 
				
			||||||
| 
						 | 
					@ -105,9 +104,10 @@ const init = async (): Promise<void> => {
 | 
				
			||||||
			more.value = false;
 | 
								more.value = false;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		offset.value = res.length;
 | 
							offset.value = res.length;
 | 
				
			||||||
		inited.value = true;
 | 
							error.value = false;
 | 
				
			||||||
		fetching.value = false;
 | 
							fetching.value = false;
 | 
				
			||||||
	}, e => {
 | 
						}, e => {
 | 
				
			||||||
 | 
							error.value = true;
 | 
				
			||||||
		fetching.value = false;
 | 
							fetching.value = false;
 | 
				
			||||||
	});
 | 
						});
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
| 
						 | 
					@ -183,30 +183,36 @@ const fetchMoreAhead = async (): Promise<void> => {
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const prepend = (item: Item): void => {
 | 
					const prepend = (item: Item): void => {
 | 
				
			||||||
	if (rootEl.value == null) return;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	if (props.pagination.reversed) {
 | 
						if (props.pagination.reversed) {
 | 
				
			||||||
		const container = getScrollContainer(rootEl.value);
 | 
							if (rootEl.value) {
 | 
				
			||||||
		if (container == null) return; // TODO?
 | 
								const container = getScrollContainer(rootEl.value);
 | 
				
			||||||
 | 
								if (container == null) return; // TODO?
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const pos = getScrollPosition(rootEl.value);
 | 
								const pos = getScrollPosition(rootEl.value);
 | 
				
			||||||
		const viewHeight = container.clientHeight;
 | 
								const viewHeight = container.clientHeight;
 | 
				
			||||||
		const height = container.scrollHeight;
 | 
								const height = container.scrollHeight;
 | 
				
			||||||
		const isBottom = (pos + viewHeight > height - 32);
 | 
								const isBottom = (pos + viewHeight > height - 32);
 | 
				
			||||||
		if (isBottom) {
 | 
								if (isBottom) {
 | 
				
			||||||
			// オーバーフローしたら古いアイテムは捨てる
 | 
									// オーバーフローしたら古いアイテムは捨てる
 | 
				
			||||||
			if (items.value.length >= props.displayLimit) {
 | 
									if (items.value.length >= props.displayLimit) {
 | 
				
			||||||
				// このやり方だとVue 3.2以降アニメーションが動かなくなる
 | 
										// このやり方だとVue 3.2以降アニメーションが動かなくなる
 | 
				
			||||||
				//items.value = items.value.slice(-props.displayLimit);
 | 
										//items.value = items.value.slice(-props.displayLimit);
 | 
				
			||||||
				while (items.value.length >= props.displayLimit) {
 | 
										while (items.value.length >= props.displayLimit) {
 | 
				
			||||||
					items.value.shift();
 | 
											items.value.shift();
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										more.value = true;
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
				more.value = true;
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		items.value.push(item);
 | 
							items.value.push(item);
 | 
				
			||||||
		// TODO
 | 
							// TODO
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
 | 
							// 初回表示時はunshiftだけでOK
 | 
				
			||||||
 | 
							if (!rootEl.value) {
 | 
				
			||||||
 | 
								items.value.unshift(item);
 | 
				
			||||||
 | 
								return;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		const isTop = isBackTop.value || (document.body.contains(rootEl.value) && isTopVisible(rootEl.value));
 | 
							const isTop = isBackTop.value || (document.body.contains(rootEl.value) && isTopVisible(rootEl.value));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (isTop) {
 | 
							if (isTop) {
 | 
				
			||||||
| 
						 | 
					@ -264,6 +270,7 @@ onDeactivated(() => {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
defineExpose({
 | 
					defineExpose({
 | 
				
			||||||
	items,
 | 
						items,
 | 
				
			||||||
 | 
						backed,
 | 
				
			||||||
	reload,
 | 
						reload,
 | 
				
			||||||
	fetchMoreAhead,
 | 
						fetchMoreAhead,
 | 
				
			||||||
	prepend,
 | 
						prepend,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
<template>
 | 
					<template>
 | 
				
			||||||
<div class="_section">
 | 
					<div class="_section">
 | 
				
			||||||
	<XNotes ref="notes" class="_content" :pagination="pagination"/>
 | 
						<XNotes class="_content" :pagination="pagination"/>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,7 +5,7 @@
 | 
				
			||||||
		<option value="replies">{{ $ts.notesAndReplies }}</option>
 | 
							<option value="replies">{{ $ts.notesAndReplies }}</option>
 | 
				
			||||||
		<option value="files">{{ $ts.withFiles }}</option>
 | 
							<option value="files">{{ $ts.withFiles }}</option>
 | 
				
			||||||
	</MkTab>
 | 
						</MkTab>
 | 
				
			||||||
	<XNotes ref="timeline" :no-gap="true" :pagination="pagination"/>
 | 
						<XNotes :no-gap="true" :pagination="pagination"/>
 | 
				
			||||||
</div>
 | 
					</div>
 | 
				
			||||||
</template>
 | 
					</template>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue