SlideShare a Scribd company logo
Generating Headless Javascript
    Tests for Validations

             js.chi
         2009/06/25
        Kurt Stephens
        CashNetUSA

    http://kurtstephens.com/
 files/headless_js_testing.pdf
Problem

   Many Views.
   Many Abstract Data Types (ADT).
   Many Models that the same ADTs.
   Many different validations on each ADT
    depending on the context (localization).
   Client and Server-side validation required.
   Client and Server are different platforms (JS
    .vs. RoR).
   Traditional JS testing in a browser eats humans
    alive.
Issues and Tech

   MVC
   Ruby and Rails
   JavaScript (aka ECMAScript)
   Localization
   Client-side and Server-side validations
   Rspec
   Seamonkey Stand-alone interpreter
       apt-get install smjs
Overview

   Server- and Client-side Validations
   Widgets
   Localization
   Validations and Regular Expressions
   Translating Ruby Regexp to JS RegExp
   Test generation and Execution
Layers
Server-Side Validation

  Controller              3. flash[:error] << person.errors
                                   4. view.render
                                                              HTML
           1. person.valid?                                 <input ...>
                                                     <span class=”error”>...</>

   Model                           View



      2. current.convert.phone.valid?(self.phone_number)



CnuLocale                                                 CnuControl
Many Views beget Widgets

  Controller             Model                 View

     1. cnu_control(person, :home_phone, ...)
  2. get_config(model.class, :home_phone)

cnu_control.yml:                                           HTML
person:                                     CnuControl   <input ...>
 home_phone:
  type: phone

    3. rx = current.convert.phone.rx
                                                             JS
                           4. js << rx.to_js



   CnuLocale                   Cnu::Ecmascript::Regexp
Overkill?
Localization

   CnuLocale
       ADTs
            Phone Number, Date, Money, Passport, etc.
       Validations
            Is user input valid?
            Uses Regexp, but can be programatic.
       Normalization
            ”+61 02 1234 5678” => ”161212345678”
       Presentation
            ”161212345678” => AU ”(02) 1234 5678”
            ”161212345678” => US ”+1 61212345678”
This Can Happen To You!
Australian Phone Number
def phone_number_au
  @@phone_number_au ||=
    begin
      sep = "[-.s]"
    /
    # +CC: +61 | 61 | b
    ((?:+|b)s*((?# country_code) 61)#{sep}?)?
    # m[:digits] will contain digits and formatting, without the + country code.
    ((?# digits)
    # 04 1234 5678      => 04 1234 5678
    # 0412345678        => 04 1234 5678
      ((?# area_code) 0?[234578]) #{sep}?((?# prefix) d{4})#{sep}?((?# suffix) d{4})
    |
    # (04) 1234 5678    => 04 1234 5678
    # (04)12345678      => 04 1234 5678
    (((?# area_code) 0?[234578]))#{sep}?((?# prefix) d{4})#{sep}?((?# suffix) d{4})
    |
    # 0412 345 678      => 04 1234 5678
    # 0412 345678       => 04 1234 5678
      ((?# area_code) 0?[234578])((?# prefix) d{2} #{sep} d{2})((?# suffix) d{1}#{sep}?d{3})
    |
    # (0412) 345 678    => 04 1234 5678
    # (0412)345 678     => 04 1234 5678
    # (0412)345678      => 04 1234 5678
    (((?# area_code) 0?[234578])((?# prefix) d{2})#{sep}?d{2})((?# suffix) d{1}#{sep}?d{3})
    |
    # 1800 123 456      => 1800 123 456
    # 1800123456        => 1800 123 456
      ((?# area_code) 1[38]00) #{sep}?((?# prefix) d{3})#{sep}?((?# suffix) d{3})
    |
    # ... A BUNCH MORE HERE! ...
    # 18 1234           => 18 '' 1234
    # 181234            => 18 '' 1234
      ((?# area_code) 1[38]) #{sep}?((?# prefix) )((?# suffix) d{4})
    )
    b
    /x.tag!
    end
end
Keeping it Managable
Elements of Style

   Optional '+' and or country code prefix:
    
        /((?:+|b)s*((?# country_code) 61)#{sep}?)?/

   Zero-length non-word assertions:
    
        /b((?# digits) d+)b/

   Tagged Captures:
    
        /((?# area_code) 0?[234578])   #{sep}?((?# prefix) d{4})#{sep}?((?#
        suffix) d{4})/

   Extended Syntax:
    
        /something else/x

   Tag Transformation:
    
        (”foo1234bar” =~ /foo((?# digits) d+)bar/.tag!)[:digits] => ”1234”
Standards: Everyone's Got One

   Ruby Regexp
       Handles (?# comments).
       Use ((?# tag) captured expr) for naming captures.
       //x enables insignificant whitespace and #
        comments.
   JS RegExp
       Does not handle //x or comments.
       b does not match BOL and EOL.
JS Regexp
   NO: b also matches $ and ^
   NO: internal comments.
   NO: extended syntax prefix.
   NO: extended syntax comments (e.g.: "n# foo barn")
   YES: non-capturing groups.
   YES: pattern multiplicity: (e.g.: /d{3}/ => /ddd/)
   NO: /A/ or /Z/
   YES: /b/ zero-width word-boundary assertion.
   YES: /B/ zero-width non-word-boundary assertion.
   YES: look-ahead assertions
   NO: look-behind assertions
Basics
Regexp in the Wild
   CnuControl
       Generate JS and executed server-side validation
        for HTML widgets for ADT values.
   CnuLocale
       Regexp with tagged captures to find relevant ADT
        data in user input.
       Normalize relevant user input to ADT.
   Cnu::Ecmascript::Regexp
       Converts Ruby Regexp objects to JS RegExp code.
       Ruby /bfoob/.to_js => JS expr "(new
        RegExp("(?:b|^|$)foo(?:b|^|$)", ""))"
My Wookie is Also My Bookie




   http://www.morningstar.nildram.co.uk/A_New_Sith.html
Testing

   Rspec test helper:
       Tests Ruby Regexp for match/not match on a string
        literal.
       Generates JS expression that is the same test on a
        JS Regexp generated from the Ruby Regexp.
       Executes the test using smjs (seamonkey JS
        interpreter)
Rspec

it "converts Regexp.phone_number_au" do
    rx = Regexp.phone_number_au
    check_rx(rx, "", false)
    check_rx(rx, "foobar", false)
    check_rx(rx, "61 (03) 1234 5678", true)
    check_rx(rx, "+61.(03).1234.5678", true)
end
Generated Ruby and JS Tests

check_rx(rx, “foobar”, false) =>


 (rx === “foobar”).should == nil


 cnu_assert(
  "(new RegExp("...", "")).test("foobar") == false",
  (new RegExp("((?:+|(?:b|^|$))s*(61)[-.s]?)?((0?[234578])[-.s]?
(d{4})[-.s]?(d{4})|((0?[234578]))[-.s]?(d{4})[-.s]?
(d{4})|(0?[234578])(d{2}[-.s]d{2})(d{1}[-.s]?d{3})|((0?
[234578])(d{2})[-.s]?d{2})(d{1}[-.s]?d{3})|(1[38]00)[-.s]?
(d{3})[-.s]?(d{3})|((1[38]00))[-.s]?(d{3})[-.s]?(d{3})|
(1[38]0)[-.s]?()(d{4})|((1[38]0))[-.s]?()(d{4})|((1[38]))
[-.s]?()(d{4})|(1[38])[-.s]?()(d{4}))(?:b|^|$)",
"")).test("foobar"),
  "==",
  false);

More Related Content

What's hot (20)

JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
Jarrod Overson
 
Min-Maxing Software Costs
Min-Maxing Software CostsMin-Maxing Software Costs
Min-Maxing Software Costs
Konstantin Kudryashov
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
Adieu
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
Wildan Maulana
 
eXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction TrainingeXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction Training
Hoat Le
 
A Re-Introduction to JavaScript
A Re-Introduction to JavaScriptA Re-Introduction to JavaScript
A Re-Introduction to JavaScript
Simon Willison
 
Clean Code Development
Clean Code DevelopmentClean Code Development
Clean Code Development
Peter Gfader
 
Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6Workshop 10: ECMAScript 6
Workshop 10: ECMAScript 6
Visual Engineering
 
ES2015 workflows
ES2015 workflowsES2015 workflows
ES2015 workflows
Jarrod Overson
 
Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJS
Visual Engineering
 
JavaScript Basics and Trends
JavaScript Basics and TrendsJavaScript Basics and Trends
JavaScript Basics and Trends
Kürşad Gülseven
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
Kirill Chebunin
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
Jorn Oomen
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
Konstantin Kudryashov
 
Writing clean code
Writing clean codeWriting clean code
Writing clean code
Angel Garcia Olloqui
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
Kacper Gunia
 
Hardened JavaScript
Hardened JavaScriptHardened JavaScript
Hardened JavaScript
KrisKowal2
 
The IoC Hydra
The IoC HydraThe IoC Hydra
The IoC Hydra
Kacper Gunia
 
Java script -23jan2015
Java script -23jan2015Java script -23jan2015
Java script -23jan2015
Sasidhar Kothuru
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Kacper Gunia
 
JavaScript and the AST
JavaScript and the ASTJavaScript and the AST
JavaScript and the AST
Jarrod Overson
 
Advanced Javascript
Advanced JavascriptAdvanced Javascript
Advanced Javascript
Adieu
 
Design Patterns in PHP5
Design Patterns in PHP5 Design Patterns in PHP5
Design Patterns in PHP5
Wildan Maulana
 
eXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction TrainingeXo SEA - JavaScript Introduction Training
eXo SEA - JavaScript Introduction Training
Hoat Le
 
A Re-Introduction to JavaScript
A Re-Introduction to JavaScriptA Re-Introduction to JavaScript
A Re-Introduction to JavaScript
Simon Willison
 
Clean Code Development
Clean Code DevelopmentClean Code Development
Clean Code Development
Peter Gfader
 
Workshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJSWorkshop 8: Templating: Handlebars, DustJS
Workshop 8: Templating: Handlebars, DustJS
Visual Engineering
 
Rich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 ApplicationRich Model And Layered Architecture in SF2 Application
Rich Model And Layered Architecture in SF2 Application
Kirill Chebunin
 
Crafting beautiful software
Crafting beautiful softwareCrafting beautiful software
Crafting beautiful software
Jorn Oomen
 
Decoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DICDecoupling with Design Patterns and Symfony2 DIC
Decoupling with Design Patterns and Symfony2 DIC
Konstantin Kudryashov
 
The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016The IoC Hydra - Dutch PHP Conference 2016
The IoC Hydra - Dutch PHP Conference 2016
Kacper Gunia
 
Hardened JavaScript
Hardened JavaScriptHardened JavaScript
Hardened JavaScript
KrisKowal2
 
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you needDutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Dutch PHP Conference - PHPSpec 2 - The only Design Tool you need
Kacper Gunia
 

Similar to Headless Js Testing (20)

How to check valid Email? Find using regex.
How to check valid Email? Find using regex.How to check valid Email? Find using regex.
How to check valid Email? Find using regex.
Poznań Ruby User Group
 
How to check valid Email? Find using regex.
How to check valid Email? Find using regex.How to check valid Email? Find using regex.
How to check valid Email? Find using regex.
Poznań Ruby User Group
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...
Codemotion
 
An introduction to Ruby
An introduction to RubyAn introduction to Ruby
An introduction to Ruby
Wes Oldenbeuving
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
Ruby gems
Ruby gemsRuby gems
Ruby gems
Papp Laszlo
 
Practical JavaScript Programming - Session 6/8
Practical JavaScript Programming - Session 6/8Practical JavaScript Programming - Session 6/8
Practical JavaScript Programming - Session 6/8
Wilson Su
 
Ruby training day1
Ruby training day1Ruby training day1
Ruby training day1
Bindesh Vijayan
 
JavaScript Regular Expression Match
JavaScript Regular Expression MatchJavaScript Regular Expression Match
JavaScript Regular Expression Match
raj upadhyay
 
Validation unit testing
Validation unit testingValidation unit testing
Validation unit testing
Jason Noble
 
How to check valid email? Find using regex(p?)
How to check valid email? Find using regex(p?)How to check valid email? Find using regex(p?)
How to check valid email? Find using regex(p?)
Visuality
 
Intro to Ruby
Intro to RubyIntro to Ruby
Intro to Ruby
Brian Hogan
 
Form validation client side
Form validation client side Form validation client side
Form validation client side
Mudasir Syed
 
And Now You Have Two Problems
And Now You Have Two ProblemsAnd Now You Have Two Problems
And Now You Have Two Problems
Luca Mearelli
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
Brian Hogan
 
3.2 javascript regex
3.2 javascript regex3.2 javascript regex
3.2 javascript regex
Jalpesh Vasa
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
旻琦 潘
 
Regex - Regular Expression Basics
Regex - Regular Expression BasicsRegex - Regular Expression Basics
Regex - Regular Expression Basics
Eterna Han Tsai
 
Rails 3 Beginner to Builder 2011 Week 8
Rails 3 Beginner to Builder 2011 Week 8Rails 3 Beginner to Builder 2011 Week 8
Rails 3 Beginner to Builder 2011 Week 8
Richard Schneeman
 
/Regex makes me want to (weep|give up|(╯°□°)╯︵ ┻━┻)\.?/i
/Regex makes me want to (weep|give up|(╯°□°)╯︵ ┻━┻)\.?/i/Regex makes me want to (weep|give up|(╯°□°)╯︵ ┻━┻)\.?/i
/Regex makes me want to (weep|give up|(╯°□°)╯︵ ┻━┻)\.?/i
brettflorio
 
How to check valid Email? Find using regex.
How to check valid Email? Find using regex.How to check valid Email? Find using regex.
How to check valid Email? Find using regex.
Poznań Ruby User Group
 
How to check valid Email? Find using regex.
How to check valid Email? Find using regex.How to check valid Email? Find using regex.
How to check valid Email? Find using regex.
Poznań Ruby User Group
 
And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...And now you have two problems. Ruby regular expressions for fun and profit by...
And now you have two problems. Ruby regular expressions for fun and profit by...
Codemotion
 
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and JasmineRails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Rails-like JavaScript Using CoffeeScript, Backbone.js and Jasmine
Raimonds Simanovskis
 
Practical JavaScript Programming - Session 6/8
Practical JavaScript Programming - Session 6/8Practical JavaScript Programming - Session 6/8
Practical JavaScript Programming - Session 6/8
Wilson Su
 
JavaScript Regular Expression Match
JavaScript Regular Expression MatchJavaScript Regular Expression Match
JavaScript Regular Expression Match
raj upadhyay
 
Validation unit testing
Validation unit testingValidation unit testing
Validation unit testing
Jason Noble
 
How to check valid email? Find using regex(p?)
How to check valid email? Find using regex(p?)How to check valid email? Find using regex(p?)
How to check valid email? Find using regex(p?)
Visuality
 
Form validation client side
Form validation client side Form validation client side
Form validation client side
Mudasir Syed
 
And Now You Have Two Problems
And Now You Have Two ProblemsAnd Now You Have Two Problems
And Now You Have Two Problems
Luca Mearelli
 
Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7Intro to Ruby - Twin Cities Code Camp 7
Intro to Ruby - Twin Cities Code Camp 7
Brian Hogan
 
3.2 javascript regex
3.2 javascript regex3.2 javascript regex
3.2 javascript regex
Jalpesh Vasa
 
A tour on ruby and friends
A tour on ruby and friendsA tour on ruby and friends
A tour on ruby and friends
旻琦 潘
 
Regex - Regular Expression Basics
Regex - Regular Expression BasicsRegex - Regular Expression Basics
Regex - Regular Expression Basics
Eterna Han Tsai
 
Rails 3 Beginner to Builder 2011 Week 8
Rails 3 Beginner to Builder 2011 Week 8Rails 3 Beginner to Builder 2011 Week 8
Rails 3 Beginner to Builder 2011 Week 8
Richard Schneeman
 
/Regex makes me want to (weep|give up|(╯°□°)╯︵ ┻━┻)\.?/i
/Regex makes me want to (weep|give up|(╯°□°)╯︵ ┻━┻)\.?/i/Regex makes me want to (weep|give up|(╯°□°)╯︵ ┻━┻)\.?/i
/Regex makes me want to (weep|give up|(╯°□°)╯︵ ┻━┻)\.?/i
brettflorio
 
Ad

More from Brian Moschel (11)

A Very Biased Comparison of MVC Libraries
A Very Biased Comparison of MVC LibrariesA Very Biased Comparison of MVC Libraries
A Very Biased Comparison of MVC Libraries
Brian Moschel
 
FuncUnit
FuncUnitFuncUnit
FuncUnit
Brian Moschel
 
Comet: an Overview and a New Solution Called Jabbify
Comet: an Overview and a New Solution Called JabbifyComet: an Overview and a New Solution Called Jabbify
Comet: an Overview and a New Solution Called Jabbify
Brian Moschel
 
Web 2.0 Expo Notes
Web 2.0 Expo NotesWeb 2.0 Expo Notes
Web 2.0 Expo Notes
Brian Moschel
 
Comet, Simplified, with Jabbify Comet Service
Comet, Simplified, with Jabbify Comet ServiceComet, Simplified, with Jabbify Comet Service
Comet, Simplified, with Jabbify Comet Service
Brian Moschel
 
Building an App with jQuery and JAXER
Building an App with jQuery and JAXERBuilding an App with jQuery and JAXER
Building an App with jQuery and JAXER
Brian Moschel
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
Brian Moschel
 
Ajax3
Ajax3Ajax3
Ajax3
Brian Moschel
 
Basic inheritance in JavaScript
Basic inheritance in JavaScriptBasic inheritance in JavaScript
Basic inheritance in JavaScript
Brian Moschel
 
Things to avoid in JavaScript
Things to avoid in JavaScriptThings to avoid in JavaScript
Things to avoid in JavaScript
Brian Moschel
 
Javascript and DOM
Javascript and DOMJavascript and DOM
Javascript and DOM
Brian Moschel
 
A Very Biased Comparison of MVC Libraries
A Very Biased Comparison of MVC LibrariesA Very Biased Comparison of MVC Libraries
A Very Biased Comparison of MVC Libraries
Brian Moschel
 
Comet: an Overview and a New Solution Called Jabbify
Comet: an Overview and a New Solution Called JabbifyComet: an Overview and a New Solution Called Jabbify
Comet: an Overview and a New Solution Called Jabbify
Brian Moschel
 
Comet, Simplified, with Jabbify Comet Service
Comet, Simplified, with Jabbify Comet ServiceComet, Simplified, with Jabbify Comet Service
Comet, Simplified, with Jabbify Comet Service
Brian Moschel
 
Building an App with jQuery and JAXER
Building an App with jQuery and JAXERBuilding an App with jQuery and JAXER
Building an App with jQuery and JAXER
Brian Moschel
 
JavaScript Functions
JavaScript FunctionsJavaScript Functions
JavaScript Functions
Brian Moschel
 
Basic inheritance in JavaScript
Basic inheritance in JavaScriptBasic inheritance in JavaScript
Basic inheritance in JavaScript
Brian Moschel
 
Things to avoid in JavaScript
Things to avoid in JavaScriptThings to avoid in JavaScript
Things to avoid in JavaScript
Brian Moschel
 
Ad

Recently uploaded (20)

European Accessibility Act & Integrated Accessibility Testing
European Accessibility Act & Integrated Accessibility TestingEuropean Accessibility Act & Integrated Accessibility Testing
European Accessibility Act & Integrated Accessibility Testing
Julia Undeutsch
 
Jira Administration Training – Day 1 : Introduction
Jira Administration Training – Day 1 : IntroductionJira Administration Training – Day 1 : Introduction
Jira Administration Training – Day 1 : Introduction
Ravi Teja
 
Improving Developer Productivity With DORA, SPACE, and DevEx
Improving Developer Productivity With DORA, SPACE, and DevExImproving Developer Productivity With DORA, SPACE, and DevEx
Improving Developer Productivity With DORA, SPACE, and DevEx
Justin Reock
 
The case for on-premises AI
The case for on-premises AIThe case for on-premises AI
The case for on-premises AI
Principled Technologies
 
LSNIF: Locally-Subdivided Neural Intersection Function
LSNIF: Locally-Subdivided Neural Intersection FunctionLSNIF: Locally-Subdivided Neural Intersection Function
LSNIF: Locally-Subdivided Neural Intersection Function
Takahiro Harada
 
Multistream in SIP and NoSIP @ OpenSIPS Summit 2025
Multistream in SIP and NoSIP @ OpenSIPS Summit 2025Multistream in SIP and NoSIP @ OpenSIPS Summit 2025
Multistream in SIP and NoSIP @ OpenSIPS Summit 2025
Lorenzo Miniero
 
Offshore IT Support: Balancing In-House and Offshore Help Desk Technicians
Offshore IT Support: Balancing In-House and Offshore Help Desk TechniciansOffshore IT Support: Balancing In-House and Offshore Help Desk Technicians
Offshore IT Support: Balancing In-House and Offshore Help Desk Technicians
john823664
 
Palo Alto Networks Cybersecurity Foundation
Palo Alto Networks Cybersecurity FoundationPalo Alto Networks Cybersecurity Foundation
Palo Alto Networks Cybersecurity Foundation
VICTOR MAESTRE RAMIREZ
 
UiPath Community Zurich: Release Management and Build Pipelines
UiPath Community Zurich: Release Management and Build PipelinesUiPath Community Zurich: Release Management and Build Pipelines
UiPath Community Zurich: Release Management and Build Pipelines
UiPathCommunity
 
ECS25 - The adventures of a Microsoft 365 Platform Owner - Website.pptx
ECS25 - The adventures of a Microsoft 365 Platform Owner - Website.pptxECS25 - The adventures of a Microsoft 365 Platform Owner - Website.pptx
ECS25 - The adventures of a Microsoft 365 Platform Owner - Website.pptx
Jasper Oosterveld
 
Evaluation Challenges in Using Generative AI for Science & Technical Content
Evaluation Challenges in Using Generative AI for Science & Technical ContentEvaluation Challenges in Using Generative AI for Science & Technical Content
Evaluation Challenges in Using Generative AI for Science & Technical Content
Paul Groth
 
Co-Constructing Explanations for AI Systems using Provenance
Co-Constructing Explanations for AI Systems using ProvenanceCo-Constructing Explanations for AI Systems using Provenance
Co-Constructing Explanations for AI Systems using Provenance
Paul Groth
 
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Peter Bittner
 
Contributing to WordPress With & Without Code.pptx
Contributing to WordPress With & Without Code.pptxContributing to WordPress With & Without Code.pptx
Contributing to WordPress With & Without Code.pptx
Patrick Lumumba
 
Maxx nft market place new generation nft marketing place
Maxx nft market place new generation nft marketing placeMaxx nft market place new generation nft marketing place
Maxx nft market place new generation nft marketing place
usersalmanrazdelhi
 
New Ways to Reduce Database Costs with ScyllaDB
New Ways to Reduce Database Costs with ScyllaDBNew Ways to Reduce Database Costs with ScyllaDB
New Ways to Reduce Database Costs with ScyllaDB
ScyllaDB
 
6th Power Grid Model Meetup - 21 May 2025
6th Power Grid Model Meetup - 21 May 20256th Power Grid Model Meetup - 21 May 2025
6th Power Grid Model Meetup - 21 May 2025
DanBrown980551
 
Create Your First AI Agent with UiPath Agent Builder
Create Your First AI Agent with UiPath Agent BuilderCreate Your First AI Agent with UiPath Agent Builder
Create Your First AI Agent with UiPath Agent Builder
DianaGray10
 
Microsoft Build 2025 takeaways in one presentation
Microsoft Build 2025 takeaways in one presentationMicrosoft Build 2025 takeaways in one presentation
Microsoft Build 2025 takeaways in one presentation
Digitalmara
 
STKI Israel Market Study 2025 final v1 version
STKI Israel Market Study 2025 final v1 versionSTKI Israel Market Study 2025 final v1 version
STKI Israel Market Study 2025 final v1 version
Dr. Jimmy Schwarzkopf
 
European Accessibility Act & Integrated Accessibility Testing
European Accessibility Act & Integrated Accessibility TestingEuropean Accessibility Act & Integrated Accessibility Testing
European Accessibility Act & Integrated Accessibility Testing
Julia Undeutsch
 
Jira Administration Training – Day 1 : Introduction
Jira Administration Training – Day 1 : IntroductionJira Administration Training – Day 1 : Introduction
Jira Administration Training – Day 1 : Introduction
Ravi Teja
 
Improving Developer Productivity With DORA, SPACE, and DevEx
Improving Developer Productivity With DORA, SPACE, and DevExImproving Developer Productivity With DORA, SPACE, and DevEx
Improving Developer Productivity With DORA, SPACE, and DevEx
Justin Reock
 
LSNIF: Locally-Subdivided Neural Intersection Function
LSNIF: Locally-Subdivided Neural Intersection FunctionLSNIF: Locally-Subdivided Neural Intersection Function
LSNIF: Locally-Subdivided Neural Intersection Function
Takahiro Harada
 
Multistream in SIP and NoSIP @ OpenSIPS Summit 2025
Multistream in SIP and NoSIP @ OpenSIPS Summit 2025Multistream in SIP and NoSIP @ OpenSIPS Summit 2025
Multistream in SIP and NoSIP @ OpenSIPS Summit 2025
Lorenzo Miniero
 
Offshore IT Support: Balancing In-House and Offshore Help Desk Technicians
Offshore IT Support: Balancing In-House and Offshore Help Desk TechniciansOffshore IT Support: Balancing In-House and Offshore Help Desk Technicians
Offshore IT Support: Balancing In-House and Offshore Help Desk Technicians
john823664
 
Palo Alto Networks Cybersecurity Foundation
Palo Alto Networks Cybersecurity FoundationPalo Alto Networks Cybersecurity Foundation
Palo Alto Networks Cybersecurity Foundation
VICTOR MAESTRE RAMIREZ
 
UiPath Community Zurich: Release Management and Build Pipelines
UiPath Community Zurich: Release Management and Build PipelinesUiPath Community Zurich: Release Management and Build Pipelines
UiPath Community Zurich: Release Management and Build Pipelines
UiPathCommunity
 
ECS25 - The adventures of a Microsoft 365 Platform Owner - Website.pptx
ECS25 - The adventures of a Microsoft 365 Platform Owner - Website.pptxECS25 - The adventures of a Microsoft 365 Platform Owner - Website.pptx
ECS25 - The adventures of a Microsoft 365 Platform Owner - Website.pptx
Jasper Oosterveld
 
Evaluation Challenges in Using Generative AI for Science & Technical Content
Evaluation Challenges in Using Generative AI for Science & Technical ContentEvaluation Challenges in Using Generative AI for Science & Technical Content
Evaluation Challenges in Using Generative AI for Science & Technical Content
Paul Groth
 
Co-Constructing Explanations for AI Systems using Provenance
Co-Constructing Explanations for AI Systems using ProvenanceCo-Constructing Explanations for AI Systems using Provenance
Co-Constructing Explanations for AI Systems using Provenance
Paul Groth
 
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Nix(OS) for Python Developers - PyCon 25 (Bologna, Italia)
Peter Bittner
 
Contributing to WordPress With & Without Code.pptx
Contributing to WordPress With & Without Code.pptxContributing to WordPress With & Without Code.pptx
Contributing to WordPress With & Without Code.pptx
Patrick Lumumba
 
Maxx nft market place new generation nft marketing place
Maxx nft market place new generation nft marketing placeMaxx nft market place new generation nft marketing place
Maxx nft market place new generation nft marketing place
usersalmanrazdelhi
 
New Ways to Reduce Database Costs with ScyllaDB
New Ways to Reduce Database Costs with ScyllaDBNew Ways to Reduce Database Costs with ScyllaDB
New Ways to Reduce Database Costs with ScyllaDB
ScyllaDB
 
6th Power Grid Model Meetup - 21 May 2025
6th Power Grid Model Meetup - 21 May 20256th Power Grid Model Meetup - 21 May 2025
6th Power Grid Model Meetup - 21 May 2025
DanBrown980551
 
Create Your First AI Agent with UiPath Agent Builder
Create Your First AI Agent with UiPath Agent BuilderCreate Your First AI Agent with UiPath Agent Builder
Create Your First AI Agent with UiPath Agent Builder
DianaGray10
 
Microsoft Build 2025 takeaways in one presentation
Microsoft Build 2025 takeaways in one presentationMicrosoft Build 2025 takeaways in one presentation
Microsoft Build 2025 takeaways in one presentation
Digitalmara
 
STKI Israel Market Study 2025 final v1 version
STKI Israel Market Study 2025 final v1 versionSTKI Israel Market Study 2025 final v1 version
STKI Israel Market Study 2025 final v1 version
Dr. Jimmy Schwarzkopf
 

Headless Js Testing

  • 1. Generating Headless Javascript Tests for Validations js.chi 2009/06/25 Kurt Stephens CashNetUSA http://kurtstephens.com/ files/headless_js_testing.pdf
  • 2. Problem  Many Views.  Many Abstract Data Types (ADT).  Many Models that the same ADTs.  Many different validations on each ADT depending on the context (localization).  Client and Server-side validation required.  Client and Server are different platforms (JS .vs. RoR).  Traditional JS testing in a browser eats humans alive.
  • 3. Issues and Tech  MVC  Ruby and Rails  JavaScript (aka ECMAScript)  Localization  Client-side and Server-side validations  Rspec  Seamonkey Stand-alone interpreter  apt-get install smjs
  • 4. Overview  Server- and Client-side Validations  Widgets  Localization  Validations and Regular Expressions  Translating Ruby Regexp to JS RegExp  Test generation and Execution
  • 6. Server-Side Validation Controller 3. flash[:error] << person.errors 4. view.render HTML 1. person.valid? <input ...> <span class=”error”>...</> Model View 2. current.convert.phone.valid?(self.phone_number) CnuLocale CnuControl
  • 7. Many Views beget Widgets Controller Model View 1. cnu_control(person, :home_phone, ...) 2. get_config(model.class, :home_phone) cnu_control.yml: HTML person: CnuControl <input ...> home_phone: type: phone 3. rx = current.convert.phone.rx JS 4. js << rx.to_js CnuLocale Cnu::Ecmascript::Regexp
  • 9. Localization  CnuLocale  ADTs  Phone Number, Date, Money, Passport, etc.  Validations  Is user input valid?  Uses Regexp, but can be programatic.  Normalization  ”+61 02 1234 5678” => ”161212345678”  Presentation  ”161212345678” => AU ”(02) 1234 5678”  ”161212345678” => US ”+1 61212345678”
  • 10. This Can Happen To You!
  • 11. Australian Phone Number def phone_number_au @@phone_number_au ||= begin sep = "[-.s]" / # +CC: +61 | 61 | b ((?:+|b)s*((?# country_code) 61)#{sep}?)? # m[:digits] will contain digits and formatting, without the + country code. ((?# digits) # 04 1234 5678 => 04 1234 5678 # 0412345678 => 04 1234 5678 ((?# area_code) 0?[234578]) #{sep}?((?# prefix) d{4})#{sep}?((?# suffix) d{4}) | # (04) 1234 5678 => 04 1234 5678 # (04)12345678 => 04 1234 5678 (((?# area_code) 0?[234578]))#{sep}?((?# prefix) d{4})#{sep}?((?# suffix) d{4}) | # 0412 345 678 => 04 1234 5678 # 0412 345678 => 04 1234 5678 ((?# area_code) 0?[234578])((?# prefix) d{2} #{sep} d{2})((?# suffix) d{1}#{sep}?d{3}) | # (0412) 345 678 => 04 1234 5678 # (0412)345 678 => 04 1234 5678 # (0412)345678 => 04 1234 5678 (((?# area_code) 0?[234578])((?# prefix) d{2})#{sep}?d{2})((?# suffix) d{1}#{sep}?d{3}) | # 1800 123 456 => 1800 123 456 # 1800123456 => 1800 123 456 ((?# area_code) 1[38]00) #{sep}?((?# prefix) d{3})#{sep}?((?# suffix) d{3}) | # ... A BUNCH MORE HERE! ... # 18 1234 => 18 '' 1234 # 181234 => 18 '' 1234 ((?# area_code) 1[38]) #{sep}?((?# prefix) )((?# suffix) d{4}) ) b /x.tag! end end
  • 13. Elements of Style  Optional '+' and or country code prefix:  /((?:+|b)s*((?# country_code) 61)#{sep}?)?/  Zero-length non-word assertions:  /b((?# digits) d+)b/  Tagged Captures:  /((?# area_code) 0?[234578]) #{sep}?((?# prefix) d{4})#{sep}?((?# suffix) d{4})/  Extended Syntax:  /something else/x  Tag Transformation:  (”foo1234bar” =~ /foo((?# digits) d+)bar/.tag!)[:digits] => ”1234”
  • 14. Standards: Everyone's Got One  Ruby Regexp  Handles (?# comments).  Use ((?# tag) captured expr) for naming captures.  //x enables insignificant whitespace and # comments.  JS RegExp  Does not handle //x or comments.  b does not match BOL and EOL.
  • 15. JS Regexp  NO: b also matches $ and ^  NO: internal comments.  NO: extended syntax prefix.  NO: extended syntax comments (e.g.: "n# foo barn")  YES: non-capturing groups.  YES: pattern multiplicity: (e.g.: /d{3}/ => /ddd/)  NO: /A/ or /Z/  YES: /b/ zero-width word-boundary assertion.  YES: /B/ zero-width non-word-boundary assertion.  YES: look-ahead assertions  NO: look-behind assertions
  • 17. Regexp in the Wild  CnuControl  Generate JS and executed server-side validation for HTML widgets for ADT values.  CnuLocale  Regexp with tagged captures to find relevant ADT data in user input.  Normalize relevant user input to ADT.  Cnu::Ecmascript::Regexp  Converts Ruby Regexp objects to JS RegExp code.  Ruby /bfoob/.to_js => JS expr "(new RegExp("(?:b|^|$)foo(?:b|^|$)", ""))"
  • 18. My Wookie is Also My Bookie http://www.morningstar.nildram.co.uk/A_New_Sith.html
  • 19. Testing  Rspec test helper:  Tests Ruby Regexp for match/not match on a string literal.  Generates JS expression that is the same test on a JS Regexp generated from the Ruby Regexp.  Executes the test using smjs (seamonkey JS interpreter)
  • 20. Rspec it "converts Regexp.phone_number_au" do rx = Regexp.phone_number_au check_rx(rx, "", false) check_rx(rx, "foobar", false) check_rx(rx, "61 (03) 1234 5678", true) check_rx(rx, "+61.(03).1234.5678", true) end
  • 21. Generated Ruby and JS Tests check_rx(rx, “foobar”, false) => (rx === “foobar”).should == nil cnu_assert( "(new RegExp("...", "")).test("foobar") == false", (new RegExp("((?:+|(?:b|^|$))s*(61)[-.s]?)?((0?[234578])[-.s]? (d{4})[-.s]?(d{4})|((0?[234578]))[-.s]?(d{4})[-.s]? (d{4})|(0?[234578])(d{2}[-.s]d{2})(d{1}[-.s]?d{3})|((0? [234578])(d{2})[-.s]?d{2})(d{1}[-.s]?d{3})|(1[38]00)[-.s]? (d{3})[-.s]?(d{3})|((1[38]00))[-.s]?(d{3})[-.s]?(d{3})| (1[38]0)[-.s]?()(d{4})|((1[38]0))[-.s]?()(d{4})|((1[38])) [-.s]?()(d{4})|(1[38])[-.s]?()(d{4}))(?:b|^|$)", "")).test("foobar"), "==", false);