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 commit18d0fcae9c
. * Revert "use wait?" This reverts commit5aa8feec9c
. * 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
|
@ -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…
Reference in New Issue