diff --git a/.gitignore b/.gitignore index 189a0ec..fdce93a 100644 --- a/.gitignore +++ b/.gitignore @@ -3,8 +3,9 @@ # If you find yourself ignoring temporary files generated by your text editor # or operating system, you probably want to add a global ignore instead: # git config --global core.excludesfile ~/.gitignore_global - + .DS_Store bin/configlet.exe bin/configlet test-exercises/ +canonical-data/ diff --git a/bin/generate-spec b/bin/generate-spec new file mode 100755 index 0000000..dc17531 --- /dev/null +++ b/bin/generate-spec @@ -0,0 +1,72 @@ +#!/usr/bin/env lua + +local json = require 'dkjson' + +local function read_file(path) + local f = assert(io.open(path, 'r')) + local contents = f:read('*a') + f:close() + return contents +end + +local function write_file(path, contents) + local f = assert(io.open(path, 'w')) + f:write(contents) + f:close() +end + +local exercise_name = arg[1] + +local exercise_directory = 'exercises/practice/' .. exercise_name + +package.path = package.path .. ';' .. exercise_directory .. '/.meta/?.lua' + +local canonical_data_url = 'https://raw.githubusercontent.com/exercism/problem-specifications/main/exercises/' .. exercise_name .. '/canonical-data.json' +local canonical_data_path = 'canonical-data/' .. exercise_name .. '.json' +local spec_path = exercise_directory .. '/' .. exercise_name .. '_spec.lua' + +assert(os.execute('mkdir -p `dirname ' .. canonical_data_path .. '`')) +assert(os.execute('curl ' .. canonical_data_url .. ' -o ' .. canonical_data_path)) + +local canonical_data_json = read_file(canonical_data_path) +local canonical_data = json.decode(canonical_data_json) + +local spec_generator = require('spec_generator') + +local function process(node) + if node.cases then + local output = {} + + if node.description then + table.insert(output, "describe('" .. node.description .. "', function()") + else + table.insert(output, "describe('" .. exercise_name .. "', function()") + end + + local cases = {} + for _, case in ipairs(node.cases) do + table.insert(cases, process(case)) + end + table.insert(output, table.concat(cases, '\n\n')) + + table.insert(output, 'end)') + + return table.concat(output, '\n') + else + local template = [[ + it('%s', function() + %s + end)]] + + return template:format(node.description, spec_generator.generate_test(node)) + end +end + +local spec = ([[ + local %s = require('%s') + + %s +]]):format(spec_generator.module_name, exercise_name, process(canonical_data)) + +write_file(spec_path, spec) +os.execute('lua-format -i ' .. spec_path) diff --git a/exercises/practice/wordy/.meta/spec_generator.lua b/exercises/practice/wordy/.meta/spec_generator.lua new file mode 100644 index 0000000..3c17c8a --- /dev/null +++ b/exercises/practice/wordy/.meta/spec_generator.lua @@ -0,0 +1,17 @@ +return { + module_name = 'wordy', + + generate_test = function(case) + if type(case.expected) == 'number' then + local template = [[ + assert.are.same(%s, wordy.answer('%s'))]] + return template:format(case.expected, case.input.question) + else + local template = [[ + assert.has_error(function() + wordy.answer('%s') + end, 'Invalid question')]] + return template:format(case.input.question) + end + end +}