typescript - Menggunakan `await` pada Protractor `element().getAttribute()` menghasilkan error: "Tipe dari operand 'await' harus berupa promise yang valid..."
Saya sedang menulis tes perilaku untuk aplikasi Angular2 menggunakan Protractor, dan saya baru dalam sintaks async/await. Masalah ini membuat saya berhenti sejenak. Bisakah seseorang menjelaskan mengapa saya mendapatkan error Typescript Type of 'await' operand must either be a valid promise or must not contain a callable 'then' member. di metode isLogoFooterPresent(), dan bagaimana cara memperbaikinya?
Saya memiliki spesifikasi Protractor sederhana berikut yang mencoba memverifikasi bahwa sebuah gambar ditampilkan dengan memeriksa lebar gambar tersebut.
Berikut cuplikan dari file e2e-spec.ts saya:
import { LoginPage, Layout } from '../page_objects';
describe('Login page', () => {
it('Should have the logo in the footer', async () => {
await LoginPage.navigateTo();
await expect(Layout.isFooterLogoPresent).toBe(true);
})
});
Dan berikut ini adalah cuplikan dari objek halaman Layout saya yang memiliki visibilitas ke gambar logo yang dimaksud. Baris dengan rantai await element(...).getAttribute(...) yang menyebabkan kesalahan.
import { browser, element, by } from 'protractor/globals';
export class Layout {
static get isFooterLogoPresent() {
return ( async () => { // <-- this wrapping is necessary to use async/await in getter method
return await element(by.css('.content-footer img')).getAttribute('naturalWidth') > 0; // <-- PROBLEM HERE
})
}
}
Sintaks berbasis promise berikut (yang berfungsi) adalah yang sedang saya coba ganti:
static get isFooterLogoPresent() {
return element(by.css('.content-footer img')).getAttribute('naturalWidth') // naturalWidth attr is 0 if image is missing
.then( imgWidth => imgWidth > 0 );
}
Omong-omong, saya menggunakan TypeScript 2.3.2 dan Protractor 5.2.0. Saya menghargai setiap saran yang Anda miliki. Terima kasih!
Jawaban #1
Saya sampai pada kesimpulan bahwa Protractor 5.2 belum siap untuk sintaks async/await. Jika ada yang berhasil membuatnya bekerja dengan baik, saya ingin tahu caranya dan versinya. Saat ini, jika Anda menelusuri ke sumber getAttribute(), itu mengembalikan objek ElementFinder, bukan Promise. Objek ini memiliki metode .then(), jadi Anda bisa menggunakan hasilnya seperti promise dengan menggabungkan .then(), tetapi TypeScript (dengan alasan yang benar) tidak akan mengenalinya sebagai promise yang tepat, yang diharapkan oleh await.
Untuk saat ini, saya menyerah pada async/await untuk proyek Protractor ini. Saya kembali menangani perilaku asinkron sepenuhnya dengan promises sebagai gantinya.
Jawaban #2
Cukup tambahkan tanda kurung untuk await Anda -
import { browser, element, by } from 'protractor/globals';
export class Layout {
static get isFooterLogoPresent() {
return ( async () => {
return (await $('.content-footer img').getAttribute('naturalWidth')) > 0;
})
}
}
Ini akan menerapkan > 0 pada nilai yang telah diselesaikan, bukan pada ekspresi perbandingan
TAPI! Anda memiliki kesalahan di sini:
await expect(Layout.isFooterLogoPresent).toBe(true);
fungsi isFooterLogoPresent masih mengembalikan sebuah promise, jadi ketika Anda menegaskan objek promise agar menjadi true, itu akan selalu true sesuai dengan cara perbandingan objek di JS bekerja. Ubah ini untuk memperbaiki tes positif palsu:
await expect(await Layout.isFooterLogoPresent).toBe(true);
