Cucumber-js: طلب الميزة: واجهة مستخدم لا تستخدم الكلمة الرئيسية `هذه`

تم إنشاؤها على ٣١ يناير ٢٠١٧  ·  16تعليقات  ·  مصدر: cucumber/cucumber-js

نظرا لعالم مثل:

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

أريد أن أكون قادرًا على كتابة:

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

بدلا من

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

سيؤدي هذا أيضًا إلى تخليص من الحصول على .bind(this) في جميع العمليات غير المتزامنة ، أو إذا كنت تفضل - التخلص من القرود باستخدام var that = this .

فائدة أخرى (IMHO) - ستساعد الناس على التخلص من شجرة الميراث للعوالم وتوجيههم بشكل أفضل نحو صلاحيات JS الأفضل

accepted enhancement

التعليق الأكثر فائدة

تمام. نظرًا لأن الجميع ليس مبرمجًا وظيفيًا ولمنع إدخال تغيير جذري ، ما رأيكم يا رفاق في اتخاذ خيار يجعل العالم يتم تمريره باعتباره المعلمة الأولى؟

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

ال 16 كومينتر

أوافق على أن هذا يعني أنك تقبل دائمًا world كوسيطة ، وهذا تغيير في واجهة برمجة التطبيقات.
أعتقد أنه مثل الموكا التي لديها --ui exports و --ui tdd و --ui bdd - يمكن أن يكون الخيار كذلك.
إنه في الأساس متغير مشروع يحدد ما إذا كانت الخطوات يتم استدعاؤها / تطبيقها على العالم ، أو قبولها باعتبارها الوسيطة الأولى.

لا أعتقد حقًا أن هذا يستحق العناء على المدى الطويل. نعم ، من الجيد استخدام خطوات السطر الأول هذه حيث يمكنك استخدام => حيث لا يمكنك ذلك. من واقع خبرتي ، كان لدي خطوات قليلة جدًا مثل هذه. أنا مندهش من أن ES6 لم يتضمن وظيفة سهم لا تحتفظ بالسياق لأن ذلك سيكون مثاليًا بالنسبة لي.

سيؤدي هذا أيضًا إلى تخليص من استخدام .bind(this) في جميع العمليات غير المتزامنة ، أو إذا كنت تفضل - التخلص من القرود باستخدام var that = this .

ألا يمكنك استخدام السهم السمين داخل تعريفات الخطوة لتجنب ذلك؟

فائدة أخرى (IMHO) - ستساعد الناس على التخلص من شجرة الميراث للعوالم وتوجيههم بشكل أفضل نحو صلاحيات JS الأفضل

هل يمكن أن تشرح هذا أكثر قليلاً / أعط مثالاً

بكلمات بسيطة: أنا أنتمي إلى مدرسة من المبرمجين الذين تجنبوا طريقة صياغة السياق كصف دراسي. كلما زاد تعرض الأشخاص للجانب المظلم من OOP ، ازداد حجم هذه المدرسة - والحركة في مجتمع JS التي منعت وظيفة السهم من الاحتفاظ بالسياق هي مثال على قوة هذه الحركة.

دون الدخول في نقاش ديني - سأقول فقط إنني أؤمن بالحياة ودع غيرك يعيش ، هل تريد استخدام الدروس؟ رائعة. من فضلك لا تجبرني على :-)

شعوري العام هو أنه يمكن أن يكون تغييرًا بسيطًا ، وسأكون سعيدًا للقيام بذلك إذا كان بإمكانك تزويدني بالاتجاه العام للطريقة التي تعتقد أنها ستتم بشكل أفضل ؛-)

عندما نحدد الخطوات ، فإننا نحدد الوظائف ، وليس الفئات ، لذا فمن المنطقي أن this ليس له مكان فيها.

أعتقد أن هذا هو وضع نموذج FP بدلاً من نموذج OOP.

osher ، أعتقد أنه يمكننا منح charlierudolph فائدة الشك في أنه لا يريد إجبارك على استخدام الفصول الدراسية. ومع ذلك ، لا ينبغي إجباره على دمج (كسر) تغييرات API أينما يستخدم هذه الحزمة ، إلا إذا كانت تقدم بعض المزايا الملموسة.

charlierudolph أعتقد من خلال "أفضل صلاحيات JS" osher تعني FP ، البرمجة الوظيفية.

IMHO هذا التغيير سيجعل تعريفات الخطوة أبسط قليلاً وأكثر منطقية. سيؤدي بشكل أساسي إلى إزالة هذا السطر: const thisWorldNotThisStep = this

بالتأكيد ليست هناك حاجة إلى استخدام .bind(this) لجميع وظائفك غير المتزامنة ، وطالما أنك تستخدم وظائف السهم ضمن تعريف الخطوة ، فلا داعي لاستخدام النمط const self = this .

المشكلة (وهي ليست مشكلة كبيرة) هي أنه داخل تعريف الخطوة ، يشير this إلى العالم ، وليس الخطوة ، وهو أمر غير بديهي.

تمام. نظرًا لأن الجميع ليس مبرمجًا وظيفيًا ولمنع إدخال تغيير جذري ، ما رأيكم يا رفاق في اتخاذ خيار يجعل العالم يتم تمريره باعتباره المعلمة الأولى؟

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

أتفق تمامًا مع فكرة حقن العالم / السياق به معلمة للخطوة. بدءًا من هذا المشروع ، يتحرك كل نظام JS البيئي لاحتضان الوظائف الجديدة التي يسمح بها ES6 تمامًا وهذا أمر جيد ❤️

إذا نظرت إلى أدوات أخرى مثل Express أو Koa ، فإنها تقوم بتعيين سياق الطلب الحالي على أنه this AND كمعامل أول من البرنامج الوسيط (وهو ما يعادل خطوة الخيار). يسمح هذا الحل بالاستخدام التقليدي للوظيفة واستخدام وظيفة السهم ES6.
ميزة أخرى للسياق باعتباره المعلمة الأولى هي ذلك

بالنسبة للحل الذي اقترحه charlierudolph ، لا أعتقد أن هذا قد ينجح على المدى الطويل: سيؤدي ذلك إلى تقسيم المجتمع إلى قسمين. لن تعمل جميع أمثلة الخيار في جميع التركيبات وسيتم تكرار المستندات في اثنتين. لا يتوهم.

لست متأكدًا من مخاوف التغيير ، الإصدار 2 هو الوقت المثالي لتقديم هذا النوع من التغيير. سيؤدي الانتظار إلى جعل / انتظار تخصص آخر.

ماذا عن تغيير Before و After لحقن 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!
  });
});

بهذه الطريقة يمكنك التقاط world في متغير وخطوة before . لن يفسد تعريف كل خطوة.

بعد ذلك ، نحتفظ بالطريقة القديمة في العمل ولكن ننشئ رسالة deprecated . أو حتى لا تفعل ذلك ، فقط اترك الخيار هناك للأشخاص الذين يرغبون في استخدام هذا النهج ويعرفون ما يفعلونه.

أخشى أن الحجة حول توافق المقتطفات الموجودة على الإنترنت هي حجة مقنعة.

حتى لو كان هناك --ui flags ، أو setWorldInjectionStrategy('argument') - سيصبح مسدودًا يتم توصيله بشكل أفضل كتغيير فاصل لإصدار رئيسي ، يتم تقديمه مع جميع المناقشات عبر الإنترنت والضجة الملائمة لمثل هذه التغييرات ، وتساعد في القضاء على الالتباس.

لذلك أصوت لفعل ذلك في الإصدار التالي من cuke ، و ... makedoing حتى يتم إطلاقه.

سيكون إصدار الكناري أو العلم المخفي بمثابة ترقية رائعة كنت سأستخدمها وأردود عليها في وقت مبكر

أود الكشف عن واجهة FP بديلة.

ماذا عن التالي؟ (استخدام غير متزامن / انتظار لتوضيح أنها صديقة للوعد أيضًا)

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 })
})

لقد اخترقت cucumber-fp الذي يقدم تعريفات خطوة وظيفية. لدي بالفعل بعض أفكار التحسين. نرحب بالتعليقات!

أقترح أن نغلق هذه المشكلة ونترك الناس يختبرون هذا الفتح الصغير. ربما في يوم من الأيام يمكننا إحضاره إلى Cucumber.js.

jbpros أفضل ألا

يجب أن يكون هذا في الواقع أمرًا بسيطًا جدًا حتى يتمكن الجميع من تطبيقه بنفسه. يعمل مقتطف الشفرة التالي جيدًا (وظيفيًا) بالنسبة لي ، مع تحذير كبير يجعله غير قابل للاستخدام:

// 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);
    }

هذا التحذير لكون كل تعريف خطوة واحدة يسجل الآن الخطأ التالي بسبب المعلمة الإضافية:

    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

إذا حاولت إضافة معلمات إضافية لحلها ، فستحصل على

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

جميع احتياجات cucumber-js هي خيار لتعطيل عمليات تدقيق وسيطات الوظيفة وستختفي هذه المشكلة. في الواقع ، عند التفكير الثاني ، يبدو أن الاختبار سينتهي أيضًا ، حيث يفترض الخيار أن رد الاتصال مطلوب بناءً على عدد الوسائط في وظيفة تعريف الخطوة. يمكن حل هذا الأمر من خلال إعطاء الأسبقية لوعد مرتجع.

andyearnshaw شكرًا قلقك بشأن التبعية "فقط لوظائف السهم في stepdefs". هذه المكتبة هي في الأساس الحل الذي أستخدمه شخصيًا للحصول على معلومات عديمة الحالة ، لقد قمت بتعبئتها لأي شخص مهتم هناك.

اعتبرها حلاً مؤقتًا حول الجدل المستمر لمثل هذا التدرج النقي API في جوهره (لقد استمر لأكثر من 4 سنوات ، صدق أو لا تصدق). كما قلت ، هذه تجربة يمكن أن تهبط في جوهرها في مرحلة ما ، وسأقدر حقًا ردود الفعل من الأشخاص الذين يستخدمونها بالفعل. إذا حصل على قدر كافٍ من الجذب ، فسيكون ذلك حجة أفضل للاندماج في الخيار.

أيضًا ، يرجى ملاحظة أنه يقدم عدة أدوات وظيفية أخرى (صغيرة) مفيدة: tap() وسياقات فرض للقراءة فقط.

إن التحقق من صحة وظائف stepdef هو بالتأكيد مشكلة كان علي التحايل عليها في هذا lib (بطريقة قبيحة تمامًا). سيكون خيار إيقاف تشغيله على CLI وبرمجيًا مفيدًا جدًا لهذا (وربما حالات استخدام أخرى). أود أن أفعل ذلك ، لكن الوقت مورد نادر بالنسبة لي في الوقت الحالي.

لا تتردد في الحصول على الإلهام من cucumber-fp لإصلاح الفحص في هذه الأثناء.

jbpros هذا رائع ، وأنا حقًا أقدر الجهد الذي بذلته هناك. كنت أكثر اختلافًا مع الرأي القائل بوجوب إغلاق هذه القضية. سألقي نظرة على مكتبتك ومعرفة ما إذا كانت تساعدني في التغلب على هذا الاختيار المزعج. 🙂

andyearnshaw ها صحيح ، شكرا للتوضيح. أوافق على ألا نتخلى عن هذه الفكرة ، وربما يكون إبقاء هذه المشكلة مفتوحًا طريقة جيدة لإبقاء الأمور شفافة ، في الواقع.

هل كانت هذه الصفحة مفيدة؟
0 / 5 - 0 التقييمات