making VueJS expressions debug-able - debugging

My vue js data has some arrays, and in the template I am trying to render them using v-for loops.
something like:
<tr v-for="d in [0,1,2,3]"><td>{{data.people[d].name}}</td></tr>
<tr v-for="d in [0,1,2,3]"><td>{{data.places[d].name}}</td></tr>
<tr v-for="d in [0,1,2,3]"><td>{{data.orders[d].id}}</td></tr>
<tr v-for="d in [0,1,2,3]"><td>{{data.other_array[d].id}}</td></tr>
<tr v-for="d in [0,1,2,3]"><td>{{data.more_array[d].som_property}}</td></tr>
and I am getting an error that looks like this:
TypeError: Cannot read property '0' of undefined
at eval (eval at createFunction (vue.js:10518), <anonymous>:2:3084)
at Proxy.renderList (vue.js:3666)
at Proxy.eval (eval at createFunction (vue.js:10518), <anonymous>:2:2915)
at Vue$3.Vue._render (vue.js:4465)
at Vue$3.updateComponent (vue.js:2765)
at Watcher.get (vue.js:3113)
at new Watcher (vue.js:3102)
at mountComponent (vue.js:2772)
at Vue$3.$mount (vue.js:8416)
at Vue$3.$mount (vue.js:10777)
logError # vue.js:1719
globalHandleError # vue.js:1710
handleError # vue.js:1699
Vue._render # vue.js:4467
updateComponent # vue.js:2765
get # vue.js:3113
Watcher # vue.js:3102
mountComponent # vue.js:2772
Vue$3.$mount # vue.js:8416
Vue$3.$mount # vue.js:10777
Vue._init # vue.js:4557
Vue$3 # vue.js:4646
(anonymous) # astromap.html:291
I do understand that it means that somewhere one of my arrays is not initialized, and I will find that array, I also know I can write using guards and use v-if .
What bothers me is that The above stack trace seems quite useless.
my Q is:
Is there a better way to write such templates, not to prevent them from failing, but so that when they do fail I will get a more indicative output?
Alternatively, Is there any other debugging magic (e.g. some lastParsedExpression secret variable) that I can use in the debug console that can tell me what was the expression that failed?
UPDATE: edited to emphasis that there are multiple places where the error could happen.

I think what you are looking for is ErrorBoundary.
Vue.component('ErrorBoundary', {
data: () => ({ error: null }),
errorCaptured (err, vm, info) {
this.error = `${err.stack}\n\nfound in ${info} of component`
return false
},
render (h) {
if (this.error) {
return h('pre', { style: { color: 'red' }}, this.error)
}
// ignoring edge cases for the sake of demonstration
return this.$slots.default[0]
}
})
<error-boundary>
<another-component/>
</error-boundary>

The first item in your v-for array is 0. The error states:
Cannot read property '0' of undefined
You're attempting to access property 0 on people
people[d].name
Where do you have people defined?
The error is telling you an object is not defined, not an array.

Related

VueJS Navigation with Inertia - Scheduler Flush Error

I have a Laravel / InertiaJS / Vue 3 app that is having issues with Nav links.
I have the following Nav link in my global app nav bar:
<NavLink :href="route('proposals.index')" :active="route().current('proposals.index')">
Proposals
</NavLink>
Which is referring to this route in my web.php routes file:
Route::get('/proposals', [\App\Http\Controllers\ProposalController::class, 'index'])->name('proposals.index');
When I login, my app redirects to this route and it works fine. When I then navigate to one of my Proposal routes like https://app.com/proposals/1, it works, but when I try to navigate back to https://app.com/proposals using this NavLink, I get the following warning and error:
Or in text format:
[Vue warn]: Unhandled error during execution of scheduler flush. This is likely a Vue internals bug. Please open an issue at https://new-issue.vuejs.org/?repo=vuejs/core
at <Inertia initialPage= {component: 'Welcome', props: {…}, url: '/', version: '164055e062448cd7a09e6bb44ac06827', scrollRegions: Array(0), …} initialComponent= {__name: 'Welcome', props: {…}, __hmrId: '6e0fb345', setup: ƒ, render: ƒ, …} resolveComponent=fn<h2> ... >
at <App>
warn2 # chunk-EQ4BACWZ.js?v=14b924b8:1613
logError # chunk-EQ4BACWZ.js?v=14b924b8:1736
handleError # chunk-EQ4BACWZ.js?v=14b924b8:1728
callWithErrorHandling # chunk-EQ4BACWZ.js?v=14b924b8:1685
flushJobs # chunk-EQ4BACWZ.js?v=14b924b8:1849
Promise.then (async)
queueFlush # chunk-EQ4BACWZ.js?v=14b924b8:1776
queueJob # chunk-EQ4BACWZ.js?v=14b924b8:1770
(anonymous) # chunk-EQ4BACWZ.js?v=14b924b8:5552
triggerEffect # chunk-EQ4BACWZ.js?v=14b924b8:675
triggerEffects # chunk-EQ4BACWZ.js?v=14b924b8:665
triggerRefValue # chunk-EQ4BACWZ.js?v=14b924b8:1184
set value # chunk-EQ4BACWZ.js?v=14b924b8:1500
swapComponent # #inertiajs_inertia-vue3.js?v=14b924b8:1474
(anonymous) # chunk-D72TQAQW.js?v=14b924b8:3479
Promise.then (async)
n2.setPage # chunk-D72TQAQW.js?v=14b924b8:3478
(anonymous) # chunk-D72TQAQW.js?v=14b924b8:3445
Promise.then (async)
n2.visit # chunk-D72TQAQW.js?v=14b924b8:3438
onClick # #inertiajs_inertia-vue3.js?v=14b924b8:1554
callWithErrorHandling # chunk-EQ4BACWZ.js?v=14b924b8:1683
callWithAsyncErrorHandling # chunk-EQ4BACWZ.js?v=14b924b8:1691
invoker # chunk-EQ4BACWZ.js?v=14b924b8:8439
chunk-EQ4BACWZ.js?v=14b924b8:5889
Uncaught (in promise) TypeError: Cannot read properties of null (reading 'type')
at unmountComponent (chunk-EQ4BACWZ.js?v=14b924b8:5889:18)
at unmount (chunk-EQ4BACWZ.js?v=14b924b8:5814:7)
at unmountChildren (chunk-EQ4BACWZ.js?v=14b924b8:5919:7)
at unmount (chunk-EQ4BACWZ.js?v=14b924b8:5826:9)
at unmountChildren (chunk-EQ4BACWZ.js?v=14b924b8:5919:7)
at unmount (chunk-EQ4BACWZ.js?v=14b924b8:5826:9)
at unmountComponent (chunk-EQ4BACWZ.js?v=14b924b8:5899:7)
at unmount (chunk-EQ4BACWZ.js?v=14b924b8:5814:7)
at unmountComponent (chunk-EQ4BACWZ.js?v=14b924b8:5899:7)
at unmount (chunk-EQ4BACWZ.js?v=14b924b8:5814:7)
The browser address is now https://app.com/proposals, but no navigation has taken place. If I then refresh the browser using Cntrl + R it navigates fine again.
Does anyone know where I can start looking for what is causing this?

Why does puppet think my custom fact is a string?

I am trying to create a custom fact I can use as the value for a class parameter in a hiera yaml file.
I am using the openstack/puppet-keystone module and I want to use fernet-keys.
According to the comments in the module I can use this parameter.
# [*fernet_keys*]
# (Optional) Hash of Keystone fernet keys
# If you enable this parameter, make sure enable_fernet_setup is set to True.
# Example of valid value:
# fernet_keys:
# /etc/keystone/fernet-keys/0:
# content: c_aJfy6At9y-toNS9SF1NQMTSkSzQ-OBYeYulTqKsWU=
# /etc/keystone/fernet-keys/1:
# content: zx0hNG7CStxFz5KXZRsf7sE4lju0dLYvXdGDIKGcd7k=
# Puppet will create a file per key in $fernet_key_repository.
# Note: defaults to false so keystone-manage fernet_setup will be executed.
# Otherwise Puppet will manage keys with File resource.
# Defaults to false
So wrote this custom fact ...
[root#puppetmaster modules]# cat keystone_fernet/lib/facter/fernet_keys.rb
Facter.add(:fernet_keys) do
setcode do
fernet_keys = {}
puts ( 'Debug keyrepo is /etc/keystone/fernet-keys' )
Dir.glob('/etc/keystone/fernet-keys/*').each do |fernet_file|
data = File.read(fernet_file)
if data
content = {}
puts ( "Debug Key file #{fernet_file} contains #{data}" )
fernet_keys[fernet_file] = { 'content' => data }
end
end
fernet_keys
end
end
Then in my keystone.yaml file I have this line:
keystone::fernet_keys: '%{::fernet_keys}'
But when I run puppet agent -t on my node I get this error:
Error: Could not retrieve catalog from remote server: Error 500 on SERVER: Server Error: Evaluation Error: Error while evaluating a Function Call, "{\"/etc/keystone/fernet-keys/1\"=>{\"content\"=>\"xxxxxxxxxxxxxxxxxxxx=\"}, \"/etc/keystone/fernet-keys/0\"=>{\"content\"=>\"xxxxxxxxxxxxxxxxxxxx=\"}}" is not a Hash. It looks to be a String at /etc/puppetlabs/code/environments/production/modules/keystone/manifests/init.pp:1144:7 on node mgmt-01
I had assumed that I had formatted the hash correctly because facter -p fernet_keys output this on the agent:
{
/etc/keystone/fernet-keys/1 => {
content => "xxxxxxxxxxxxxxxxxxxx="
},
/etc/keystone/fernet-keys/0 => {
content => "xxxxxxxxxxxxxxxxxxxx="
}
}
The code in the keystone module looks like this (with line numbers)
1142
1143 if $fernet_keys {
1144 validate_hash($fernet_keys)
1145 create_resources('file', $fernet_keys, {
1146 'owner' => $keystone_user,
1147 'group' => $keystone_group,
1148 'subscribe' => 'Anchor[keystone::install::end]',
1149 }
1150 )
1151 } else {
Puppet does not necessarily think your fact value is a string -- it might do, if the client is set to stringify facts, but that's actually beside the point. The bottom line is that Hiera interpolation tokens don't work the way you think. Specifically:
Hiera can interpolate values of any of Puppet’s data types, but the
value will be converted to a string.
(Emphasis added.)

YML syntax error

I want to have a multi-line bit of markdown java in a yam file. I tried many things but I guess I don't quite get the quoting rules of Yaml.
{
title: Museum,
body: |
"```java
code code code
java2",
answers: [
"`museum`",
"`museum.getFloor(3)`",
"`museum.getFloor(3).getExhibit(5)`",
"`museum.getFloor(3).getExhibit(5).getCurator()`",
"`museum.getFloor(3).getExhibit(5).getCurator().name`",
"`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"
]
}
Produces:
/Users/pitosalas/.rbenv/versions/2.3.1/lib/ruby/2.3.0/psych.rb:377:in `parse': (generator/test.yml): found character that cannot start any token while scanning for the next token at line 3 column 9 (Psych::SyntaxError)
YAML has two styles: the JSON like flow style and the much better human readable block style.
Roughly speaking you can have nested structures each style nested within itself and can have flow style nested within block style, but block style nested within flow style is not allowed.
Your to level { and } are flow style but you try to introduce, with |, a literal block style scalar within that flow style. Replace the flow style with block style upwards from that scalar:
title: Museum
body: |
"```java
code code code
java2"
answers: [
"`museum`",
"`museum.getFloor(3)`",
"`museum.getFloor(3).getExhibit(5)`",
"`museum.getFloor(3).getExhibit(5).getCurator()`",
"`museum.getFloor(3).getExhibit(5).getCurator().name`",
"`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"
]
and your YAML is fine. Note that the double quotes "around" the value for the key body are not going to be stripped when loading, maybe that is not what you intended.
You should IMO not leave out the trailing , after the last value in the (flow style) sequence that is the value for answers. This will certainly lead to errors when you extend the list and forget to put in the trailing comma on the line above.
I would personally go for block style all the way:
title: Museum
body: |
"```java
code code code
java2"
answers:
- "`museum`"
- "`museum.getFloor(3)`"
- "`museum.getFloor(3).getExhibit(5)`"
- "`museum.getFloor(3).getExhibit(5).getCurator()`"
- "`museum.getFloor(3).getExhibit(5).getCurator().name`"
- "`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"
When dealing with YAML file generation that is convoluted or complex, or when it's not working as I expect, I revert to letting Ruby show me the way:
require 'yaml'
body = <<EOT
"```java
code code code
java2
"
EOT
answers = %w(
`museum`
`museum.getFloor(3)`
`museum.getFloor(3).getExhibit(5)`
`museum.getFloor(3).getExhibit(5).getCurator()`
`museum.getFloor(3).getExhibit(5).getCurator().name`
`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`
)
obj = {
"title" => "Museum",
"body" => body,
"answers" => answers
}
puts obj.to_yaml
Which, in this case, outputs:
---
title: Museum
body: |
"```java
code code code
java2
"
answers:
- "`museum`"
- "`museum.getFloor(3)`"
- "`museum.getFloor(3).getExhibit(5)`"
- "`museum.getFloor(3).getExhibit(5).getCurator()`"
- "`museum.getFloor(3).getExhibit(5).getCurator().name`"
- "`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"
If you then pass that YAML back into the parser, you should get the original data structure back:
YAML.load(obj.to_yaml)
# => {"title"=>"Museum",
# "body"=>"\"```java\n" +
# "code code code\n" +
# "java2\n" +
# "\"\n",
# "answers"=>
# ["`museum`",
# "`museum.getFloor(3)`",
# "`museum.getFloor(3).getExhibit(5)`",
# "`museum.getFloor(3).getExhibit(5).getCurator()`",
# "`museum.getFloor(3).getExhibit(5).getCurator().name`",
# "`museum.getFloor(3).getExhibit(5).getCurator().name.toUpper()`"]}

Docpad: confused about extending template data

I'm totally confused about adding mongo data to template data. I haven't even started trying to get the data from a database as I can't get my templates to see test data (see below). This is in docpad.coffee for the moment, but ultimately g will be the output of mongoDB.
events:
extendTemplateData: (opts) ->
# {templateData} = opts
getGigsData: ->
g = { "date" : "3-4-2013", "location" : "Gent" }
return g
opts.templateData["getGigsData"] = getGigsData
And I hope to access it with <%= #getGigsData().date %>
Thanks so much for some guidance
I should add that this design is based on wanting to make it easy for the band to add gigs, without letting them edit the page content itself as I fear they would mess up the markup - if there are other ways to achieve this goal, I'd be pleased to hear.
Tried this locally. And hit the issue:
debug: Emitting the event: extendTemplateData
→ [2014-02-14 01:38:50.030] [/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/node_modules/docpad/out/lib/docpad.js:1184] [DocPad.emitSerial]
error: Something went wrong with the action
→ [2014-02-14 01:38:50.037] [/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/node_modules/docpad/out/lib/interfaces/console.js:107] [ConsoleInterface.destroyWithError]
error: An error occured:
ReferenceError: getGigsData is not defined
at Object.docpadConfig.events.extendTemplateData (/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/docpad.coffee:42:44)
at ambi (/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/node_modules/docpad/node_modules/ambi/out/lib/ambi.js:25:27)
at DocPad.<anonymous> (/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/node_modules/docpad/out/lib/docpad.js:995:25)
at ambi (/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/node_modules/docpad/node_modules/ambi/out/lib/ambi.js:23:18)
at Task.<anonymous> (/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/node_modules/docpad/node_modules/event-emitter-grouped/out/lib/event-emitter-grouped.js:45:23)
at ambi (/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/node_modules/docpad/node_modules/ambi/out/lib/ambi.js:23:18)
at fire (/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/node_modules/docpad/node_modules/taskgroup/out/lib/taskgroup.js:163:25)
at b (domain.js:183:18)
at Domain.run (domain.js:123:23)
at Task.fire (/Users/balupton/Projects/docpad-extras/skeletons/so-21747504/node_modules/docpad/node_modules/taskgroup/out/lib/taskgroup.js:173:25)
at processImmediate [as _immediateCallback] (timers.js:330:15)
Which indicates that the error is actually inside our event handler, rather than inside our code. That for some reason getGigsData is not being set, despite our:
getGigsData: ->
g = { "date" : "3-4-2013", "location" : "Gent" }
return g
Examining the code, as a CoffeeScript user, I found the issue. As a non-coffeescript user, you can use the coffeescript compiler on the coffeescript website http://coffeescript.org to see the compiled javascript, which is:
({
events: {
extendTemplateData: function(opts) {
({
getGigsData: function() {
var g;
g = {
"date": "3-4-2013",
"location": "Gent"
};
return g;
}
});
return opts.templateData["getGigsData"] = getGigsData;
}
}
});
As we can see that is definitely not what we expected. We are just defining getGigsData inside an object, then doing nothing with it.
The issue is that we used a colon instead of an equals sign, so getGigsData: -> instead of getGigsData = ->. This is not a coffeescript thing, but you would have run into the same issue if this was javascript too, albeit javascript may be a bit more obvious due to the necessary squiggly braces around object definitions.
As a sidenote, if you prefer to use JavaScript with DocPad for whatever reason, that is totally supported. You could use a docpad.json or docpad.js file for your docpad configuration file. Another option, is to continue using CoffeeScript then just wrap JavaScript code within the backtick, see: http://coffeescript.org/#embedded

SyntaxError on pageobject while accessing a select_list within fieldset

I'm trying to access a select_list within a fieldset though Cheezy's pageobject.
The total html is far too long to post (well over 200 lines for just the fieldset), but I can supply the lines with all of the id's and such.
fieldset:
<fieldset class="dartPayer-Insurance" style="width: 730px;">
select_list:
<select id="dartPayer-Payer" style="width: 235px;">
Line in the pageobject I am attempting to use:
select_list(:payer_insurance){ element(:class => "dartPayer-Insurance").select_list_element(:id => "dartPayer-PayerList") }
The error I am getting when I try to run my cucumber test:
(eval):1: syntax error, unexpected '(', expecting $end
{:id=>"dartPayer-Insurance"}(identifier)
^ (SyntaxError)
This error occurs when I try to set the select_list with this line:
self.send(field, input) (Where field is "payer_insurance=" and input is "UMA")
This line works for other pages, so I am fairly certain this is not part of the problem. I'm sure it's a simple bit of syntax in the pageobject line, but I can't find any documentation for using the pageobject quite like I'm trying to. The only reference I can find is within a previous question I asked: Accessing a table within a table (Watir/PageObject)
Could anyone please tell me what I have done wrong?
Thank you in advance for your help.
Update: An example that reproduces the problem:
Given a page with the html:
<fieldset class="dartPayer-Insurance" style="width: 730px;">
<select id="dartPayer-Payer" style="width: 235px;">
<option value="UMA">UMA</option>
</select>
</fieldset>
And a page object defined as:
class MyPage
include PageObject
select_list(:payer_insurance){ element(:class => "dartPayer-Insurance").select_list_element(:id => "dartPayer-PayerList") }
def input_payer(field, input)
self.send(field, input)
end
end
Running the following code:
browser = Watir::Browser.new
browser.goto('C:\Scripts\Misc\Programming\PageObject\test.htm')
page = MyPage.new(browser)
field = "payer_insurance="
input = "UMA"
page.input_payer(field, input)
Generates the following exception:
C:/Ruby193/lib/ruby/gems/1.9.1/gems/page-object-0.9.0/lib/page-object/platforms/watir_webdriver/page_object.rb:968:in `instance_eval': (eval):1: syntax error, unexpected '(', expecting $end (SyntaxError)
{:class=>"dartPayer-Insurance"}(identifier)
^
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/page-object-0.9.0/lib/page-object/platforms/watir_webdriver/page_object.rb:968:in `find_watir_element'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/page-object-0.9.0/lib/page-object/platforms/watir_webdriver/page_object.rb:907:in `element_for'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/page-object-0.9.0/lib/page-object/element_locators.rb:11:in `element'
from pageobject.rb:7:in `block in <class:MyPage>'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/page-object-0.9.0/lib/page-object.rb:379:in `instance_eval'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/page-object-0.9.0/lib/page-object.rb:379:in `call_block'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/page-object-0.9.0/lib/page-object/accessors.rb:1089:in `block in standard_methods'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/page-object-0.9.0/lib/page-object/accessors.rb:246:in `block in select_list'
from pageobject.rb:10:in `input_payer'
from pageobject.rb:25:in `<main>'
Solution
The accessor you want for the select list is:
select_list(:payer_insurance){ element(:fieldset, :class => "dartPayer-Insurance").select_list_element(:id => "dartPayer-Payer") }
Problem
You were getting the syntax error due to the following part:
element(:class => "dartPayer-Insurance")
In the API docs for element, you can see that method definition is:
(Object) element(tag, identifier = {:index => 0})
Finds an element
Parameters:
the (Symbol) — name of the tag for the element
identifier (Hash) (defaults to: {:index => 0}) — how we find an element. You can use a multiple paramaters by combining of any of the following except xpath
The original code was missing the tag parameter, which caused the exception.
Note that the select list id was also incorrect - using dartPayer-PayerList instead of dartPayer-Payer.

Resources