require "spec_helper" require "fileutils" RSpec.describe Asciidoctor::BSI do context "when xref_error.adoc compilation" do around do |example| FileUtils.rm_f "spec/assets/xref_error.err" example.run Dir["spec/assets/xref_error*"].each do |file| next if file.match?(/adoc$/) FileUtils.rm_f(file) end end it "generates error file" do expect do mock_pdf Metanorma::Compile.new .compile("spec/assets/xref_error.adoc", type: "bsi", no_install_fonts: true) end.to(change { File.exist?("spec/assets/xref_error.err") } .from(false).to(true)) end end it "Warns of illegal doctype" do FileUtils.rm_f "test.err" Asciidoctor.convert(<<~"INPUT", backend: :bsi, header_footer: true) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: pizza text INPUT expect(File.read("test.err")) .to include "pizza is not a recognised document type" end it "No style warning if decimal point" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} == Clause 8.1 INPUT expect(File.read("test.err")).not_to include "possible decimal point" end it "Style warning if decimal comma" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} == Clause 8,1 INPUT expect(File.read("test.err")).to include "possible decimal comma" end it "warns that code of practice may contain requirement" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: code-of-practice == Random clause The widget shall not be larger than 15 cm. INPUT expect(File.read("test.err")) .to include "Code Of Practice clause may contain requirement" Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: technical-report == Random clause The widget is required not to be larger than 15 cm. INPUT expect(File.read("test.err")) .not_to include "Technical Report clause may contain requirement" end it "warns that specification may contain requirement in informative text" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: specification == Random clause The widget is not be larger than 15 cm. NOTE: the widget shall not be good. [appendix,obligation=informative] == Annex The widget should not be good INPUT expect(File.read("test.err")) .to include "Specification clause may contain requirement" expect(File.read("test.err")) .not_to include "Specification clause may contain recommendation" end it "warns that specification may contain recommendation, permission "\ "or possibility in normative text" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: specification == Random clause The widget should be larger than 15 cm. The widget can be larger than 15 cm. [appendix,obligation=normative] == Annex The widget may not be good INPUT expect(File.read("test.err")) .not_to include "Specification clause may contain requirement" expect(File.read("test.err")) .to include "Specification clause may contain recommendation" expect(File.read("test.err")) .to include "Specification clause may contain permission" expect(File.read("test.err")) .to include "Specification clause may contain possibility" end it "warns that guide may contain recommendation in informative text" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: guide == Random clause The widget is not be larger than 15 cm. NOTE: the widget shall not be good. [appendix,obligation=informative] == Annex The widget should not be good INPUT expect(File.read("test.err")) .to include "Guide clause may contain requirement" expect(File.read("test.err")) .to include "Guide clause may contain recommendation" end it "warns that guide contains normative annexes" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: guide [appendix,obligation=informative] == Annex 1 [appendix,obligation=normative] == Annex INPUT expect(File.read("test.err")) .to include "Guide contains normative annex: Annex" expect(File.read("test.err")) .not_to include "Guide contains normative annex: Annex 1" end it "warns of ambiguous word 'must'" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: technical-report == Random clause The widget must be larger than 15 cm. INPUT expect(File.read("test.err")) .to include "text contains ambiguous 'must'" end it "warns of superscript ordinals" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: technical-report == Random clause This is the 22^nd^ rule INPUT expect(File.read("test.err")) .to include "text contains ordinal superscript" end it "warns of Non-approved reference in Normative References" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} [bibliography] == Normative References * [[[XYZ,IESO 121]]] _Standard_ INPUT expect(File.read("test.err")) .to include "reference other than BSI, CEN, CENELEC, ISO, IEC "\ "not expected as normative" end it "warns of withdrawn standards in Normative References" do VCR.use_cassette "isobib_get_639_1967" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib-cache: [bibliography] == Normative References * [[[XYZ,ISO 639:1967]]] _Standard_ INPUT expect(File.read("test.err")) .to include "Do not cite withdrawn standards" end end it "warns of withdrawn standards in Normative References" do mock_fdis Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib-cache: [bibliography] == Normative References * [[[XYZ,ISO/FDIS 17664-1]]] _Standard_ INPUT expect(File.read("test.err")) .to include "Do not cite unpublished standards" end it "Warning if main title contains document type" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :title-main-en: A British Standard on Widgets :no-isobib: INPUT expect(File.read("test.err")) .to include "Main Title may name document type" end it "Warning if intro title contains document type" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :title-intro-en: A British Standard on Widgets :no-isobib: INPUT expect(File.read("test.err")) .to include "Title Intro may name document type" end it "Warning if term definition starts with upper case character" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} == Terms and Definitions === Term Part of the specialized vocabulary of a particular field. INPUT expect(File.read("test.err")) .to include "term definition starts with upper case character" end it "Warning if term definition is circular" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} == Terms and Definitions === Vocabulary Part of the specialized vocabulary of a particular field. INPUT expect(File.read("test.err")) .to include "term definition may be circular" end it "Warning if symbol definition is circular" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} == Symbols and Abbreviated Terms stem:[a_1]:: the notion of the dimension of a particular field a:: Part of the list of the dimension of a particular field. V:: part of the V of a particular field X:: Part of the notion of a particular field INPUT expect(File.read("test.err")) .to include "a: symbol definition ends with period" expect(File.read("test.err")) .to include "a1: symbol definition starts with article" expect(File.read("test.err")) .to include "V: symbol definition may be circular" expect(File.read("test.err")) .to include "X: symbol definition starts with upper case character" end it "Warning if annexes do not appear in citation order" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} <> <> <> [[a1]] [appendix] == First annex [[a2]] [appendix] == Second annex [[a3]] [appendix] == Third annex INPUT expect(File.read("test.err")) .to include "First annex should be annex #3" expect(File.read("test.err")) .to include "Third annex should be annex #1" end it "Warning if annexes not cited properly" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: specification <> shall be cited. People should cite <>. <> should be cited. You may cite <> at length. [[a1]] [appendix,obligation=normative] == First annex [[a2]] [appendix,obligation=informative] == Second annex INPUT expect(File.read("test.err")) .to include "Specification must cite normative annex as requirement: People should cite" expect(File.read("test.err")) .to include "Specification must cite informative annex as recommendation or statement: You may cite" Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: :doctype: code-of-practice <> shall be cited. People should cite <>. <> should be cited. You may cite <> at length. [[a1]] [appendix,obligation=normative] == First annex [[a2]] [appendix,obligation=informative] == Second annex INPUT expect(File.read("test.err")) .to include "Code Of Practice must cite normative annex as recommendation: XREF shall be cited" expect(File.read("test.err")) .to include "Code Of Practice must cite informative annex as statement: People should cite" end it "Warn if more than 5 levels of subclause" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause === Clause ==== Clause ===== Clause ====== Clause [level=6] ====== Clause INPUT expect(File.read("test.err")) .to include "Exceeds the maximum clause depth of 5" end it "Warn if more than three ordered lists in a clause" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause . A .. B ... C a . A .. B a . B INPUT expect(File.read("test.err")) .not_to include "More than 3 ordered lists in a numbered clause" Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause . A .. B ... C a . A .. B a . B .. C a . C INPUT expect(File.read("test.err")) .to include "More than 3 ordered lists in a numbered clause" end it "Warn if nothing before list" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause . A .. B ... C INPUT expect(File.read("test.err")) .to include "All lists must be preceded by introductory phrase" end it "Warn if no introductory text before list" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause NOTE: X * A * B * C INPUT expect(File.read("test.err")) .to include "All lists must be preceded by introductory phrase" end it "Do not warn if introductory text before list" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause X * A * B * C INPUT expect(File.read("test.err")) .not_to include "All lists must be preceded by introductory phrase" end it "Warn if no colon or full stop before list" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause X * A * B * C INPUT expect(File.read("test.err")) .to include "All lists must be preceded by colon or full stop" end it "Do not warn if colon or full stop before list" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause X. * A * B * C X: . A . B . C INPUT expect(File.read("test.err")) .not_to include "All lists must be preceded by colon or full stop" end it "Warn of list punctuation after colon" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause X: * this is; * another; * Sentence. X: . this is . another; . sentence X: . sentence. INPUT expect(File.read("test.err")) .to include "List entry after colon must start with lowercase letter: Sentence." expect(File.read("test.err")) .not_to include "List entry after colon must start with lowercase letter: another;." expect(File.read("test.err")) .to include "List entry after colon must end with semicolon: this is" expect(File.read("test.err")) .to include "Final list entry after colon must end with full stop: sentence" expect(File.read("test.err")) .not_to include "Final list entry after colon must end with full stop: sentence." end it "Warn of list punctuation after full stop" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause X. * This is; * Another. * sentence. INPUT expect(File.read("test.err")) .to include "List entry after full stop must end with full stop: This is;" expect(File.read("test.err")) .not_to include "List entry after full stop must end with full stop: Another." expect(File.read("test.err")) .to include "List entry after full stop must start with uppercase letter: sentence." end it "Warn of provisions in admonitions" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) = Document title Author :docfile: test.adoc :nodoc: :no-isobib: == Clause [WARNING] -- This shall be bad. This can be bad. This should be bad. This may be bad. -- INPUT expect(File.read("test.err")) .to include "admonition may contain requirement" expect(File.read("test.err")) .to include "admonition may contain recommendation" expect(File.read("test.err")) .to include "admonition may contain permission" expect(File.read("test.err")) .to include "admonition may contain possibility" end it "warns that example may contain requirement" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} == Terms and Definitions === Term [example] This shall be bad. This can be bad. This should be bad. This may be bad. INPUT expect(File.read("test.err")) .to include "Example may contain requirement" expect(File.read("test.err")) .not_to include "Example may contain recommendation" end it "warns of incorrect spacing around plus-minus sign" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} === Term 9 ± 2 2±9 INPUT expect(File.read("test.err")) .to include "no space before plus-minus sign: 2±9" expect(File.read("test.err")) .to include "space after plus-minus sign: 9 ± 2" end it "warns of nested subscripts" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} === Term stem:[D_{1_max}] stem:[D^{1^max}] INPUT expect(File.read("test.err")) .to include "Nested subscript" expect(File.read("test.err")) .to include "Nested superscript" end it "warns of empty table data cells" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} === Term |=== | | A | B | C |=== INPUT expect(File.read("test.err")) .to include "Empty table cell" end it "warns of empty table header cells" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} === Term |=== | C | A | B | |=== INPUT expect(File.read("test.err")) .to include "Empty table cell" end it "does not warn of no empty table cells" do Asciidoctor.convert(<<~"INPUT", *OPTIONS) #{VALIDATING_BLANK_HDR} === Term |=== | C | A | B | X |=== INPUT expect(File.read("test.err")) .not_to include "Empty table cell" end end private def mock_fdis expect(RelatonIso::IsoBibliography).to receive(:get) .with("ISO/FDIS 17664-1", nil, lang: "en", title: "Standard", usrlbl: nil) do RelatonIsoBib::XMLParser.from_xml(<<~"OUTPUT") #{Date.today} Traitement de produits de soins de santé Informations relatives au traitement des dispositifs médicaux à fournir par le fabricant du dispositif Partie 1: Titre manque Traitement de produits de soins de santé — Informations relatives au traitement des dispositifs médicaux à fournir par le fabricant du dispositif — Partie 1: Titre manque https://www.iso.org/standard/81720.html https://www.iso.org/contents/data/standard/08/17/81720.detail.rss ISO/FDIS 17664-1 urn:iso:std:iso-fdis:17664:-1:stage-50.00:ed-1:fr 17664 International Organization for Standardization ISO www.iso.org 1 en fr 50 00 unknown ISO/FDIS OUTPUT end end