diff --git a/lib/senec/local/state.rb b/lib/senec/local/state.rb index 4c80cb0..749593a 100644 --- a/lib/senec/local/state.rb +++ b/lib/senec/local/state.rb @@ -15,18 +15,30 @@ def initialize(connection:) # ... # }; def names(language: :de) - response(language:).match(FILE_REGEX)[0].split("\n").each_with_object({}) do |line, hash| - key, value = line.match(LINE_REGEX)&.captures - next unless key && value + js_content = response(language:) - hash[key.to_i] = value - end + # Extract the matched content + match = js_content.match(FILE_REGEX) + return unless match + + # Extract the JSON-like part + json_like = "{#{match[1]}}" + + # The keys are numbers, which is not valid JSON, so we need to convert them to strings + json = json_like.gsub(/(\d+)\s*:/, '"\1":') + + # Convert the JSON string to a Ruby hash + hash = JSON.parse(json) + + # Convert keys from strings to integers + hash.transform_keys(&:to_i) end private - FILE_REGEX = /var system_state_name = \{(.*?)\};/m - LINE_REGEX = /(\d+)\s*:\s*"(.*)"/ + # Regex pattern to match the system_state_name definition in the JavaScript file + # The file may be minimized, so we need to be flexible with whitespace and line breaks + FILE_REGEX = /system_state_name\s*=\s*{\s*([^}]*)\s*}/m def response(language:) res = connection.get url(language:) diff --git a/spec/lib/senec/local/state_spec.rb b/spec/lib/senec/local/state_spec.rb index da8ec46..9020671 100644 --- a/spec/lib/senec/local/state_spec.rb +++ b/spec/lib/senec/local/state_spec.rb @@ -25,6 +25,12 @@ def mock_response JS end + def mock_response_minified + <<~JS + var foo=123,system_state_name={0:"EXAMPLE 0",1:"EXAMPLE 1",2:"EXAMPLE 2",10:"EXAMPLE 10",11:"EXAMPLE 11",16:"EXAMPLE 16"},system_type_name={0:"foo"}; + JS + end + describe '#names' do subject(:names) { state.names(language:) } @@ -69,6 +75,16 @@ def mock_response it { is_expected.to eq(expected_hash) } end + context 'when JS is minified' do + let(:language) { :en } + + before do + stub_request(:any, "https://#{senec_host}/js/EN-en.js").to_return(body: mock_response_minified) + end + + it { is_expected.to eq(expected_hash) } + end + context 'when language is invalid' do let(:language) { :xyz }