Cucumber-js: Permintaan fitur: UI yang tidak menggunakan kata kunci `this`

Dibuat pada 31 Jan 2017  ·  16Komentar  ·  Sumber: cucumber/cucumber-js

Mengingat dunia seperti:

require('cucumber').defineSupportCode( ({setWorldConstructor:world}) => {
    world(class { 
      constructor(p) { ... }
      foo(bar) { return new Promise(.... ) }
    })
})

Saya ingin bisa menulis:

  When(/^I do the foo with (.*)$/i, (ctx, bar) => ctx.foo(bar) );

dari pada

  When(/^I do the foo with (.*)$/i, function(bar) {
      return this.foo(bar)
  });

Ini juga akan membebaskan saya dari monkeying .bind(this) pada semua operasi async, atau jika Anda lebih suka - singkirkan monkeying dengan var that = this .

Satu lagi manfaat (IMHO) - ini akan membantu orang turun dari pohon warisan untuk dunia dan mengarahkan mereka lebih baik ke kekuatan JS yang lebih baik

accepted enhancement

Komentar yang paling membantu

Oke. Karena tidak semua orang adalah pemrogram fungsional dan untuk mencegah pengenalan perubahan yang melanggar, apa pendapat kalian tentang membuat opsi yang membuat dunia dilewatkan sebagai parameter pertama?

defineSupportCode(({setWorldInjectionStrategy}) => {
  setWorldInjectionStrategy('this') // default
  setWorldInjectionStrategy('argument') // makes world be the first argument to steps and hooks 
})

Semua 16 komentar

Saya setuju bahwa itu berarti Anda selalu menerima world sebagai argumen, dan itu adalah perubahan API.
Saya pikir seperti moka yang memiliki --ui exports dan --ui tdd dan --ui bdd - cucue juga bisa.
Ini pada dasarnya adalah variabel proyek yang menentukan apakah langkah-langkah dipanggil/diterapkan di dunia, atau menerimanya sebagai argumen pertama.

Saya benar-benar tidak berpikir ini akan sia-sia dalam jangka panjang. Ya itu bagus untuk langkah 1 baris di mana Anda bisa menggunakan => mana Anda tidak dapat melakukannya. Dalam pengalaman saya, saya memiliki sangat sedikit langkah seperti ini. Saya terkejut ES6 tidak menyertakan fungsi panah yang tidak mempertahankan konteks karena itu ideal bagi saya.

Ini juga akan membebaskan saya dari monyet .bind(this) pada semua operasi async, atau jika Anda lebih suka - singkirkan monyet dengan var that = this .

Tidak bisakah Anda menggunakan panah gemuk di dalam definisi langkah untuk menghindari ini?

Satu lagi manfaat (IMHO) - ini akan membantu orang turun dari pohon warisan untuk dunia dan mengarahkan mereka lebih baik ke kekuatan JS yang lebih baik

Bisakah Anda menjelaskan ini sedikit lebih banyak / berikan contoh

Dengan kata sederhana: Saya termasuk dalam sekolah programmer yang telah menghindari cara mengungkapkan konteks sebagai kelas. Semakin banyak orang terpapar sisi gelap OOP, sekolah ini tumbuh lebih besar - dan gerakan di komunitas JS yang mencegah fungsi panah mempertahankan konteks adalah contoh kekuatan gerakan ini.

Tanpa masuk ke debat agama - saya hanya akan mengatakan saya percaya pada hidup dan membiarkan hidup, Anda ingin menggunakan kelas? Bagus. Tolong jangan paksa aku :-)

Perasaan umum saya adalah bahwa itu bisa menjadi perubahan kecil, dan saya akan dengan senang hati melakukannya jika Anda dapat memberi saya arahan umum tentang bagaimana menurut Anda itu akan dilakukan dengan baik ;-)

Saat kita mendefinisikan langkah, kita mendefinisikan fungsi, bukan kelas, jadi secara logis this tidak memiliki tempat di dalamnya.

Saya pikir ini adalah situasi untuk paradigma FP daripada paradigma OOP.

@osher Saya pikir kami dapat memberi @charlierudolph manfaat dari keraguan bahwa dia tidak ingin memaksa Anda untuk menggunakan kelas. Yang mengatakan, dia tidak boleh dipaksa untuk mengintegrasikan (melanggar) perubahan API di mana pun dia menggunakan paket ini, kecuali jika itu menawarkan beberapa keuntungan nyata.

@charlierudolph Saya pikir dengan "kekuatan JS yang lebih baik" @osher berarti FP, Pemrograman Fungsional.

IMHO perubahan ini akan membuat definisi langkah sedikit lebih sederhana dan lebih logis. Itu pada dasarnya hanya akan menghapus baris ini: const thisWorldNotThisStep = this

Jelas tidak perlu melakukan monkey .bind(this) ke semua fungsi async Anda, dan selama dalam definisi langkah Anda menggunakan fungsi panah, tidak perlu menggunakan pola const self = this .

Masalahnya (yang bukan masalah besar) adalah bahwa di dalam definisi langkah, this merujuk ke dunia, bukan langkah, yang kontra-intuitif.

Oke. Karena tidak semua orang adalah pemrogram fungsional dan untuk mencegah pengenalan perubahan yang melanggar, apa pendapat kalian tentang membuat opsi yang membuat dunia dilewatkan sebagai parameter pertama?

defineSupportCode(({setWorldInjectionStrategy}) => {
  setWorldInjectionStrategy('this') // default
  setWorldInjectionStrategy('argument') // makes world be the first argument to steps and hooks 
})

Saya sangat setuju dengan ide untuk menyuntikkan dunia/konteks memiliki parameter langkah. Dimulai dengan proyek ini, semua ekosistem JS bergerak untuk sepenuhnya merangkul fungsionalitas baru yang diizinkan oleh ES6 dan itu hal yang baik ❤️

Jika Anda melihat alat lain seperti Express atau Koa, mereka menetapkan konteks permintaan saat ini sebagai this DAN sebagai parameter pertama middleware (ini setara dengan langkah mentimun). Solusi ini memungkinkan penggunaan fungsi tradisional dan penggunaan fungsi panah ES6.
Keuntungan lain dari konteks sebagai parameter pertama adalah bahwa

Untuk solusi yang diusulkan oleh @charlierudolph , saya rasa ini tidak akan berhasil dalam jangka panjang: ini akan membagi komunitas menjadi dua. Semua contoh mentimun tidak akan berfungsi di semua instalasi dan dokumen akan diduplikasi menjadi dua. Tidak mewah.

Saya tidak yakin tentang kekhawatiran perubahan melanggar, v2 adalah waktu yang tepat untuk memperkenalkan perubahan semacam ini. Menunggu akan memaksa untuk membuat/menunggu jurusan lain.

Bagaimana kalau kita mengubah Before dan After menjadi inject world :

defineSupportCode(function({After, Before, Given}) {
  let world;

  // Asynchronous Callback
  Before(function (w, scenarioResult, callback) {
    world = w;
    callback();
  });
  After(function (world, scenarioResult, callback) {
    callback();
  });

  Given('I access the world', () => {
    assert(world); // Yay!
  });
});

Dengan cara itu Anda dapat menangkap world dalam variabel dengan langkah before . Itu tidak akan mengacaukan setiap definisi langkah.

Selanjutnya, kami mempertahankan cara kerja lama tetapi menghasilkan pesan deprecated . Atau bahkan jangan lakukan itu, biarkan saja opsi di sana untuk orang-orang yang ingin menggunakan pendekatan itu dan tahu apa yang mereka lakukan.

Saya khawatir argumen tentang kompatibilitas cuplikan yang ditemukan online adalah argumen yang meyakinkan.

Bahkan jika akan ada --ui flags, atau setWorldInjectionStrategy('argument') - itu menjadi gotcha yang lebih baik dikomunikasikan sebagai perubahan utama dari versi utama, disajikan dengan semua diskusi online dan keributan yang sesuai dengan perubahan tersebut, dan membantu menghilangkan kebingungan.

Jadi saya memilih untuk melakukannya di versi cuke berikutnya, dan ...makedoing sampai rilis.

Versi kenari atau bendera tersembunyi akan menjadi promosi luar biasa yang akan saya gunakan dan umpan balik sejak awal

Saya ingin mengekspos antarmuka FP alternatif.

Bagaimana dengan yang berikut ini? (menggunakan async/menunggu untuk mengilustrasikannya juga ramah-janji)

import {initialize, Given, Before} from 'cucumber/fn'

// specify a function that returns the initial context:
initialize(async () => ({ a: 42 }))

Before({ timeout: 10 }, async (ctx) => {
  await doStuff(ctx.a)
})

Given(/^a step passes with {number}$/, async (ctx, number) => {
  const newA = await computeStuff(ctx.a, number)
  // tell cucumber about the new context:
  return Object.assign({}, ctx, { a: newA })
})

Saya telah meretas bersama mentimun-fp yang menawarkan definisi langkah fungsional. Saya sudah punya beberapa ide perbaikan. Umpan balik selamat datang!

Saya sarankan kita menutup masalah ini dan membiarkan orang bereksperimen dengan lib kecil itu. Mungkin suatu saat kita bisa membawanya ke Cucumber.js.

@jbpros Saya lebih suka untuk tidak menginstal ketergantungan lain supaya saya dapat menggunakan fungsi panah dalam pengujian saya.

Ini sebenarnya harus sangat sederhana bagi semua orang untuk mengimplementasikannya sendiri. Cuplikan kode berikut berfungsi cukup baik (secara fungsional) untuk saya, dengan peringatan besar yang membuatnya tidak dapat digunakan:

// Don't rely on `this` in step definitions. It's 2021 for crying out loud.
const definitionFunctionWrapper = (fn) =>
    function(...args) {
        return fn(...args.slice(0, -1), this);
    }

Peringatan itu adalah setiap definisi langkah sekarang mencatat kesalahan berikut karena parameter tambahan:

    Error: function uses multiple asynchronous interfaces: callback and promise
       to use the callback interface: do not return a promise
       to use the promise interface: remove the last argument to the function

Jika Anda mencoba menambahkan parameter tambahan untuk mengatasinya, Anda mendapatkan

function has 3 arguments, should have 1 (if synchronous or returning a promise) or 2 (if accepting a callback)

Semua kebutuhan mentimun-js adalah opsi untuk menonaktifkan pemeriksaan argumen fungsi dan masalah ini akan hilang. Sebenarnya setelah dipikir-pikir sepertinya tes akan habis juga, karena mentimun mengasumsikan bahwa panggilan balik diperlukan berdasarkan jumlah argumen dalam fungsi definisi langkah. Ini bisa diatasi dengan mengutamakan janji yang dikembalikan.

@andyearnshaw terima kasih atas masukan Anda, saya mendengar kekhawatiran Anda tentang ketergantungan "hanya untuk fungsi panah di stepdefs". Pustaka ini pada dasarnya adalah solusi yang saya gunakan secara pribadi untuk mendapatkan langkah defs stateless, saya hanya mengemasnya untuk siapa saja yang tertarik di luar sana.

Anggap saja sebagai solusi sementara seputar perdebatan yang sedang berlangsung untuk API stepdef murni di inti (sudah berlangsung selama lebih dari 4 tahun, percaya atau tidak). Seperti yang saya katakan, ini adalah eksperimen yang dapat mendarat di inti di beberapa titik dan saya akan sangat menghargai umpan balik dari orang-orang yang benar-benar menggunakannya. Jika mendapat daya tarik yang cukup, itu akan menjadi argumen yang lebih baik untuk mengintegrasikan dalam mentimun.

Juga, harap perhatikan bahwa ia menawarkan beberapa alat fungsional (kecil) lain yang berguna: tap() dan konteks hanya-baca yang ditegakkan.

Pemeriksaan arity pada fungsi stepdef jelas merupakan masalah yang harus saya hindari di lib ini (dengan cara yang sangat buruk). Opsi untuk mematikannya baik pada CLI dan secara terprogram akan sangat berguna untuk ini (dan kemungkinan kasus penggunaan lainnya). Saya ingin melakukan itu, tetapi waktu adalah sumber daya yang langka bagi saya saat ini.

Jangan ragu untuk mendapatkan inspirasi dari mentimun-fp untuk memperbaiki arity check sementara itu.

@jbpros itu bagus, dan saya sangat menghargai upaya yang Anda lakukan di sana. Saya lebih tidak setuju dengan sentimen bahwa masalah ini harus ditutup. Saya akan melihat perpustakaan Anda dan melihat apakah itu membantu saya mengatasi cek yang mengganggu itu. 🙂

@andyearnshaw ha benar, terima kasih atas klarifikasinya. Saya setuju kita tidak boleh membuang ide ini dan membiarkan masalah ini tetap terbuka mungkin merupakan cara yang baik untuk menjaga semuanya tetap transparan.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat